通过鼠标滚轮在画布Angular + D3上缩放

时间:2018-11-05 11:54:48

标签: javascript html angular d3.js

我想通过鼠标滚轮对HTML画布进行缩放,就像在Google地图上一样。 我的项目中有两个画布,一个用于显示图像,一个用于编辑图像。我根据鼠标的位置来进行画布的转换和缩放。 一切顺利。缩放和缩放后绘制。问题是当我尝试在缩放后保存图形的原始位置时-位置不正确。

HTML:

<canvas id="backgroundCanvas" #backgroundCanvas class="background-canvas" width="930" height="710"></canvas>                        
<canvas #editCanvas mouseWheel class="edit-canvas" width="930" height="710" [style.cursor]="editMode ? 'pointer' : '-webkit-grab'"  (mouseWheelUp)="mouseWheelUpFunc($event)" (mouseWheelDown)="mouseWheel($event)"></canvas> 

JS:

        this.canvas1 = d3.select("#editCanvas");
    this.context = this.canvas1.node().getContext("2d");
    this.width = this.canvas1.property("width");
    this.height = this.canvas1.property("height");
    this.canvas1.call(d3.zoom()
        .scaleExtent([1, 4])
        .on("zoom",  () => {

                if (this.zoomStep === 0) {
                    this.isZoomed = false; //set isZoomed to false for disable to drag the image
                }
                var wheel = d3.event.sourceEvent.wheelDelta/120;//n or -n
                var zoom = 0;
                if(wheel < 0)//if it's zoom out
                {
                    this.zoomStep--;
                    this.setCurrentScale(this.zoomFactor, false);
                    this.resetBackgroundTopLeft();
                    console.log("wheel is under 0 "); 
                    zoom = 1/1.05;
                }
                else//if it's zoom in
                {
                    this.zoomStep++;
                    this.isZoomed = true;//set isZoomed to true for enable to drag the image
                    this.setCurrentScale(this.zoomFactor, true);
                    zoom = 1.05;
                }
                this.currentzoom *= zoom; //set the current zoom for know whem to stop
                this.clearBackgroundCanvas(); // clear the background image befor draw it again.
                /*********************************change the background canvas (where the image is)****************************************************/
                this.backgroundContext.save();
                this.backgroundContext.translate(
                    d3.event.transform.x,
                    d3.event.transform.y
                );
                this.backgroundContext.scale(d3.event.transform.k, d3.event.transform.k);
                this.backgroundContext.drawImage(this.curentImage, this.imageTopLeft.x, this.imageTopLeft.y ,this.img.w * this.currentScale, this.img.h * this.currentScale);
                this.backgroundContext.restore();

                /***********************************change the edit canvas (where the tags are)**************************************************/

                this.editContext.save();
                this.editContext.translate(
                    d3.event.transform.x,
                    d3.event.transform.y
                );
                this.editContext.scale(d3.event.transform.k, d3.event.transform.k);
                this.draw() //clear and then draw the marker again
                this.editContext.restore();

                /*************************************************************************************/

            }))
                .on("mousedown.zoom", () =>{
                this.onMouseDown1(d3.event);    
            })

/**This function set the sacle to zoom In or Out according the mouse wheel*/
setCurrentScale = (scale: number, zoomIn: boolean) => {
    this.currentScale *= zoomIn ?  scale : 1 / scale;
    }

/**This function clear all the canvase area */
    clearBackgroundCanvas() {
        this.backgroundContext.clearRect(0, 0, this.canvas.w, this.canvas.h);
    }


    onMouseDown1(evt: MouseEvent) {
        var coordinates = d3.mouse(this.canvas1.node());

        console.log("onMouseDown" + evt.offsetX , evt.offsetY ,coordinates)

        if (this.editMode) {
            if (this.isInDrawingArea(evt.offsetX, evt.offsetY, this.imageTopLeft)) {
                // return relative mouse position
                this.currentDrawnMarkerStart = {
                     x: coordinates[0],
                     y: coordinates[1]
                };
                this.isDrawingRect = true;
                if(this.scale == null)
                    this.scale ={k :1 };
                this.drawRectBorder(
                    this.currentDrawnMarkerStart.x ,
                    this.currentDrawnMarkerStart.y ,
                    250*this.currentScale*this.scale.k,
                    250*this.currentScale*this.scale.k,
                    '#004de6',2*this.scale.k);//color for the rect tag on drawing
                    const m = {
                        x: this.currentDrawnMarkerStart.x,
                        y: this.currentDrawnMarkerStart.y,
                        w: 250*this.currentScale,
                        h: 250*this.currentScale,
                        isSelected: false,
                        isHovered: false
                    };
                    this.addMarker(m);


            }
        } else if (!this.isDragging && this.isZoomed) {
            this.dragStart = {
                x: evt.offsetX,
                y: evt.offsetY
            };
            this.isDragging = true;
        }
    }




    drawRectBorder = (x0: number, y0: number, w: number, h: number, color: string, borderW: number = 1) => {
        this.editContext.strokeStyle = color;
        this.editContext.lineWidth = borderW;
        this.editContext.beginPath();
        this.editContext.rect(x0, y0, w, h);
        this.editContext.stroke();
        this.editContext.closePath();

    }

addMarker = (r: IMarker) => {

        console.log(this.currentScale)
        const original = editorUtil.transformMarkerToOriginal(editorUtil.getMarkerTopLeft(r),
            this.imageTopLeft, this.currentScale);
        // Save coordinates on canvas
        this.currentMarkers.push(original);
        console.log(original)
    }

/** Get the marker's top left corner, with absolute values for w,h */
export const getMarkerTopLeft = (m: IMarker): IMarker => {
  const res: IMarker = {
    x: m.x + (m.w < 0 ? m.w : 0),
    y: m.y + (m.h < 0 ? m.h : 0),
    w: Math.abs(m.w),
    h: Math.abs(m.h),
    isSelected: m.isSelected,
    isHovered: m.isHovered
  };
  return res;
};


/** Get the marker's coordinates with regards to the original image dimensions */
export const transformMarkerToOriginal = (m: IMarker, imageTopLeft: Coordinate, scale: number): IMarker => {
    const res: IMarker = {
      x: Math.floor((m.x - imageTopLeft.x) / scale),
      y: Math.floor((m.y - imageTopLeft.y) / scale),
      w: Math.floor(Math.abs(m.w / scale)),
      h: Math.floor(Math.abs(m.h / scale)),

      isSelected: false,
      isHovered: false
    };
    return res;
};

谢谢!

0 个答案:

没有答案