|
| 1 | +import type { IAABBBounds, Matrix } from '@visactor/vutils'; |
| 2 | +import { BasePlugin } from '../../base/base-plugin'; |
| 3 | +import type { IVChartPlugin, IVChartPluginService } from '../interface'; |
| 4 | +import { registerVChartPlugin } from '../register'; |
| 5 | +import type { IVChart } from '../../../core/interface'; |
| 6 | +import { |
| 7 | + matrixAllocate, |
| 8 | + transformPointForCanvas, |
| 9 | + mapToCanvasPointForCanvas, |
| 10 | + registerGlobalEventTransformer, |
| 11 | + registerWindowEventTransformer, |
| 12 | + vglobal |
| 13 | +} from '@visactor/vrender-core'; |
| 14 | + |
| 15 | +export class RotatePlugin extends BasePlugin implements IVChartPlugin { |
| 16 | + static readonly pluginType: 'vchart' = 'vchart'; |
| 17 | + |
| 18 | + static readonly specKey = 'rotate'; |
| 19 | + |
| 20 | + static readonly type: string = 'rotatePlugin'; |
| 21 | + readonly type: string = 'rotatePlugin'; |
| 22 | + |
| 23 | + private rotateDegree: number; |
| 24 | + private matrix: Matrix; |
| 25 | + private vglobal_mapToCanvasPoint: any; // 保存vrender中vglobal的mapToCanvasPoint原方法 |
| 26 | + private _vchart: IVChart; |
| 27 | + |
| 28 | + constructor() { |
| 29 | + super(RotatePlugin.type); |
| 30 | + } |
| 31 | + |
| 32 | + onInit(service: IVChartPluginService) { |
| 33 | + const { globalInstance: vchart } = service; |
| 34 | + if (!vchart) { |
| 35 | + return; |
| 36 | + } |
| 37 | + this._vchart = vchart; |
| 38 | + //将函数rotate90WithTransform绑定到table实例上,一般情况下插件不需要将api绑定到table实例上,可以直接自身实现某个api功能 |
| 39 | + vchart.rotate90WithTransform = this.rotate90WithTransform; |
| 40 | + vchart.cancelTransform = this.cancelTransform; |
| 41 | + } |
| 42 | + |
| 43 | + rotate90WithTransform = (rotateDom: HTMLElement) => { |
| 44 | + this.rotateDegree = 90; |
| 45 | + const rotateCenter = |
| 46 | + rotateDom.clientWidth < rotateDom.clientHeight |
| 47 | + ? Math.max(rotateDom.clientWidth, rotateDom.clientHeight) / 2 |
| 48 | + : Math.min(rotateDom.clientWidth, rotateDom.clientHeight) / 2; |
| 49 | + const domRect = this._vchart.getContainer().getBoundingClientRect(); |
| 50 | + const x1 = domRect.left; |
| 51 | + const y1 = domRect.top; |
| 52 | + const x2 = domRect.right; |
| 53 | + const y2 = domRect.bottom; |
| 54 | + |
| 55 | + rotateDom.style.transform = 'rotate(90deg)'; |
| 56 | + rotateDom.style.transformOrigin = `${rotateCenter}px ${rotateCenter}px`; |
| 57 | + const getRect = () => { |
| 58 | + return { |
| 59 | + x1, |
| 60 | + y1, |
| 61 | + x2, |
| 62 | + y2 |
| 63 | + } as IAABBBounds; |
| 64 | + }; |
| 65 | + // 获取视口尺寸的通用方法 |
| 66 | + const getViewportDimensions = () => { |
| 67 | + // 浏览器环境 |
| 68 | + if (typeof window !== 'undefined') { |
| 69 | + return { |
| 70 | + width: window.innerWidth || document.documentElement.clientWidth, |
| 71 | + height: window.innerHeight || document.documentElement.clientHeight |
| 72 | + }; |
| 73 | + } |
| 74 | + // 如果有 vglobal 上的方法可以使用 |
| 75 | + if (vglobal && 'getViewportSize' in vglobal && vglobal.getViewportSize) { |
| 76 | + // @ts-ignore |
| 77 | + return vglobal.getViewportSize(); |
| 78 | + } |
| 79 | + // 默认使用容器的尺寸 |
| 80 | + return rotateDom.getBoundingClientRect(); |
| 81 | + }; |
| 82 | + |
| 83 | + const getMatrix = () => { |
| 84 | + const viewPortWidth = getViewportDimensions().width; //获取整个视口的尺寸 |
| 85 | + const domRect = this._vchart.getContainer().getBoundingClientRect(); //TODO 这个地方应该获取窗口的宽高 最好能从vglobal上直接获取 |
| 86 | + const x1 = domRect.top; |
| 87 | + const y1 = viewPortWidth - domRect.right; |
| 88 | + |
| 89 | + const matrix = matrixAllocate.allocate(1, 0, 0, 1, 0, 0); |
| 90 | + matrix.translate(x1, y1); |
| 91 | + const centerX = rotateCenter - x1; |
| 92 | + const centerY = rotateCenter - y1; |
| 93 | + matrix.translate(centerX, centerY); |
| 94 | + matrix.rotate(Math.PI / 2); |
| 95 | + matrix.translate(-centerX, -centerY); |
| 96 | + this.matrix = matrix; |
| 97 | + return matrix; |
| 98 | + }; |
| 99 | + registerGlobalEventTransformer(vglobal, this._vchart.getContainer(), getMatrix, getRect, transformPointForCanvas); |
| 100 | + registerWindowEventTransformer( |
| 101 | + this._vchart.getStage().window, |
| 102 | + this._vchart.getContainer(), |
| 103 | + getMatrix, |
| 104 | + getRect, |
| 105 | + transformPointForCanvas |
| 106 | + ); |
| 107 | + this.vglobal_mapToCanvasPoint = vglobal.mapToCanvasPoint; |
| 108 | + vglobal.mapToCanvasPoint = mapToCanvasPointForCanvas; |
| 109 | + //transformPointForCanvas和mapToCanvasPointForCanvas时相对应的 |
| 110 | + //具体逻辑在 VRender/packages/vrender-core/src/common/event-transformer.ts中 |
| 111 | + // 可以自定义这两个函数 来修改事件属性,transformPointForCanvas中将坐标转换后存放了_canvasX _canvasY,mapToCanvasPointForCanvas中加以利用 |
| 112 | + // 在VTable的touch文件中,利用到了_canvasX _canvasY 所以如果自定义上面两个函数也需提供_canvasX _canvasY |
| 113 | + }; |
| 114 | + cancelTransform = (rotateDom: HTMLElement) => { |
| 115 | + this.rotateDegree = 0; |
| 116 | + rotateDom.style.transform = 'none'; |
| 117 | + rotateDom.style.transformOrigin = 'none'; |
| 118 | + const domRect = this._vchart.getContainer().getBoundingClientRect(); |
| 119 | + const x1 = domRect.left; |
| 120 | + const y1 = domRect.top; |
| 121 | + const x2 = domRect.right; |
| 122 | + const y2 = domRect.bottom; |
| 123 | + |
| 124 | + const getRect = () => { |
| 125 | + return { |
| 126 | + x1, |
| 127 | + y1, |
| 128 | + x2, |
| 129 | + y2 |
| 130 | + } as IAABBBounds; |
| 131 | + }; |
| 132 | + const getMatrix = () => { |
| 133 | + const matrix = matrixAllocate.allocate(1, 0, 0, 1, 0, 0); |
| 134 | + matrix.translate(x1, y1); |
| 135 | + return matrix; |
| 136 | + }; |
| 137 | + registerGlobalEventTransformer(vglobal, this._vchart.getContainer(), getMatrix, getRect, transformPointForCanvas); |
| 138 | + registerWindowEventTransformer( |
| 139 | + this._vchart.getStage().window, |
| 140 | + this._vchart.getContainer(), |
| 141 | + getMatrix, |
| 142 | + getRect, |
| 143 | + transformPointForCanvas |
| 144 | + ); |
| 145 | + vglobal.mapToCanvasPoint = this.vglobal_mapToCanvasPoint; |
| 146 | + }; |
| 147 | + |
| 148 | + release() { |
| 149 | + this._vchart = null; |
| 150 | + this.vglobal_mapToCanvasPoint = null; |
| 151 | + this.matrix = null; |
| 152 | + super.release(); |
| 153 | + } |
| 154 | +} |
| 155 | + |
| 156 | +export const registerRotatePlugin = () => { |
| 157 | + registerVChartPlugin(RotatePlugin); |
| 158 | +}; |
0 commit comments