我想通过鼠标滚轮对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;
};
谢谢!