2016-07-08 108 views
1

我正在通過從api接收的一些數據構建畫布,這一切都很好。是幾天反正我是這樣的事實stucked與下面的代碼`canvas.addEventListener( '輪子',(事件:的MouseWheelEvent)=> { event.preventDefault();縮放/平移之後的畫布座標

let coords = Positioning.transformedPoint(
     event.pageX - canvas.offsetLeft, 
     event.pageY - canvas.offsetTop 
    ); 

    canvasMethods.clear(); 
    canvasMethods.translate(coords.x, coords.y); 

    if (event.wheelDeltaY > 0) { 
     canvasMethods.scale(ZoomDirection.ZOOM_IN); 
    } else if (event.wheelDeltaY < 0) { 
     canvasMethods.scale(ZoomDirection.ZOOM_OUT); 
    } 

    canvasMethods.translate(-coords.x, -coords.y); 

    this._renderFn(); 
    }, false); 

    canvas.addEventListener('mousedown', (event: MouseEvent) => { 
    event.preventDefault(); 

    this._dragging = true; 
    this._dragStart = Positioning.transformedPoint(
     event.clientX - canvas.offsetLeft, 
     event.clientY - canvas.offsetTop 
    ); 
    }, false); 

    canvas.addEventListener('dblclick', (event: MouseEvent) => { 
    let coords = Positioning.transformedPoint(
     event.clientX - canvas.offsetLeft, 
     event.clientY - canvas.offsetTop 
    ); 
    this._clickFn(coords); 
    }); 

    canvas.addEventListener('mousemove', (event: MouseEvent) => { 
    if (this._dragging) { 
     event.preventDefault(); 

     this._dragEnd = Positioning.transformedPoint(
     event.pageX - canvas.offsetLeft, 
     event.pageY - canvas.offsetTop 
    ); 

     let coords = Positioning.transformedPoint(
     event.clientX - canvas.offsetLeft, 
     event.clientY - canvas.offsetTop 
    ); 

     canvasMethods.translate(coords.x - this._dragStart.x, coords.y - this._dragStart.y); 
     canvasMethods.clear(); 

     this._renderFn(); 
     this._dragStart = this._dragEnd; 
    } 
    }, false); 

    canvas.addEventListener('mouseup', (event: MouseEvent) => { 
    event.preventDefault(); 

    this._dragging = false; 
    this._dragStart = null; 
    this._dragEnd = null; 
    }) 
}` 

我在正常尺度下得到正確的座標,但只要我縮放,我會得到一個增量誤差(基本上實際點和鼠標光標之間的距離越來越大),我無法計算出原因。矩陣我使用SVG方法作爲下面的包裝方式`export class Positioning {svg = document.createElementNS('http://www.w3.org/2000/svg','svg'); private static xform = Positioning.svg.createSVGMatrix();

static transformedPoint(x: number, y: number): SVGPoint { 
    let coords = Positioning.svg.createSVGPoint(); 

    coords.x = x; 
    coords.y = y; 

    return coords.matrixTransform(Positioning.xform.inverse()); 
} 

}`

我知道,這在某種程度上與caling做,但我真想不通怎麼弄帳戶比例,並做適當的操作以獲取該比例。我也檢查了這個答案Zoom Canvas to Mouse Cursor,這很準確,但實際上他以某種我無法重新考慮的方式來解釋它。有其他人面臨同樣的問題?

+0

你有正確的想法:通過[轉換矩陣]路由所有的轉換(http://simonsarris.com/blog/471-a-transformation-class-for-canvas-to-keep-track-轉換矩陣),然後使用該矩陣在轉換和未轉換的座標之間轉換。 – markE

+0

是的,我相當接近,但我無法弄清楚拼圖的最後一塊,你的意思是通過反轉矩陣轉換和未轉換之間進行轉換?因爲你可以看到我的服務已經反轉矩陣。 –

回答

2

我已經解決了這個問題,我忘記了一件重要的事情,來跟蹤我的轉換。現在,我將鏈接代碼,以便誰可能會遇到我的相同問題(如果您不使用Typescript可以避免類型的打印)

基本上我使用SVG矩陣方法來跟蹤發生了什麼在畫布上。

這是通過存儲由createSVGMatrix()創建的未轉換的畫布(1,0,0,1,0,0)的基本矩陣並通過本機SVGMatrix跟蹤轉換來獲取Canvas轉換帳戶的類正在更新原始矩陣的方法。然後當我需要的時候,我只是使用變換後的點方法來回退鼠標正確的x,y座標,並按比例縮放到矩陣中。

export class Positioning { 
static svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); 
static MatrixTransformationProxy = Positioning.svg.createSVGMatrix(); 

static transformedPoint(x: number, y: number): SVGPoint { 
    let coords = Positioning.svg.createSVGPoint(); 

    coords.x = x; 
    coords.y = y; 

    return coords.matrixTransform(Positioning.MatrixTransformationProxy.inverse()); 
} 

static translateProxy(x: number, y: number) { 
    Positioning.MatrixTransformationProxy = Positioning.MatrixTransformationProxy.translate(x, y); 
} 

static scaleUniformProxy(scaleValue: number) { 
    Positioning.MatrixTransformationProxy = Positioning.MatrixTransformationProxy.scale(scaleValue); 
} 

}

我使用的包裝爲調用畫布法和相對定位方法來更新MatrixTransformationProxy這樣

export class CanvasMethods { 
static getSharedInstance(): CanvasMethods { 
    return sharedInstance; 
} 

private _canvas: HTMLCanvasElement; 

getCanvas(): HTMLCanvasElement { 
    return this._canvas; 
} 

getContext(): CanvasRenderingContext2D { 
    return this._canvas.getContext('2d'); 
} 

registerCanvas(canvas: HTMLCanvasElement): void { 
    this._canvas = canvas; 
} 

getCanvasBoundingRect(): BoundingRect { 
    return new BoundingRect(0, 0, this._canvas.width, this._canvas.height); 
} 

clear(): void { 
    this.getContext().save(); 
    this.getContext().setTransform(1, 0, 0, 1, 0, 0); 
    this.getContext().clearRect(0, 0, this._canvas.width, this._canvas.height); 
    this.getContext().restore(); 
} 

scale(direction: ZoomDirection): void { 
    let options = { //TODO get this from constructor options 
    scaleValueOut: 0.8, 
    scaleValueIn: 1.1 
    }; 

    if (direction === ZoomDirection.ZOOM_OUT) { 
    Positioning.scaleUniformProxy(options.scaleValueOut); 
    this.getContext().scale(options.scaleValueOut, options.scaleValueOut); 
    } else if (direction === ZoomDirection.ZOOM_IN) { 
    Positioning.scaleUniformProxy(options.scaleValueIn); 
    this.getContext().scale(options.scaleValueIn, options.scaleValueIn); 
    } 
} 

translate(x: number, y: number): void { 
    Positioning.translateProxy(x, y); 
    this.getContext().translate(x, y); 
} 
帆布方法保持同步我的畫布轉型與我ProxyMatrix

}

const sharedInstance = new CanvasMethods(); }