如何解决如何使用离子在HTML5画布中创建可拖动线?
如何在画布中拖动线条?
我可以使用此answer在画布中添加线条。
在这种情况下,answer行拖动有效,但是当我在离子应用程序中使用它时,它不起作用。
这是我的代码:
import { Component,OnInit,ViewChild,ElementRef } from '@angular/core';
@Component({
selector: 'app-home',templateUrl: 'home.page.html',styleUrls: ['home.page.scss'],})
export class HomePage {
@ViewChild('canvasDraw',{ static: false }) canvas: ElementRef;
canvasElement: any;
lines: any[];
isDown: boolean = false;
startX: number;
startY: number;
nearest: any;
offsetX: any;
offsetY: any;
constructor() {
setTimeout(() => {
let ctx = this.canvasElement.getContext('2d');
},1000)
}
ngOnInit() {
}
ngAfterViewInit(): void {
this.canvasElement = this.canvas.nativeElement;
// canvas lets
let canvas = document.getElementById("canvasDraw");
// line lets
// let this.nearest;
this.lines = [];
this.lines.push({ x0: 75,y0: 25,x1: 125,y1: 25 });
this.lines.push({ x0: 75,y0: 100,y1: 100 });
this.lines.push({ x0: 50,y0: 35,x1: 50,y1: 85 });
this.lines.push({ x0: 150,x1: 150,y1: 85 });
this.draw();
}
reOffset() {
let canvas = document.getElementById("canvasDraw");
let BB = canvas.getBoundingClientRect();
this.offsetX = BB.left;
this.offsetY = BB.top;
}
ionViewWillLeave() {
}
// select the this.nearest line to the mouse
closestLine(mx,my) {
let dist = 100000000;
let index,pt;
for (let i = 0; i < this.lines.length; i++) {
//
let xy = this.closestXY(this.lines[i],mx,my);
//
let dx = mx - xy.x;
let dy = my - xy.y;
let thisDist = dx * dx + dy * dy;
if (thisDist < dist) {
dist = thisDist;
pt = xy;
index = i;
}
}
let line = this.lines[index];
return ({ pt: pt,line: line,originalLine: { x0: line.x0,y0: line.y0,x1: line.x1,y1: line.y1 } });
}
// linear interpolation -- needed in setClosestLine()
lerp(a,b,x) {
return (a + x * (b - a));
}
// find closest XY on line to mouse XY
closestXY(line,my) {
let x0 = line.x0;
let y0 = line.y0;
let x1 = line.x1;
let y1 = line.y1;
let dx = x1 - x0;
let dy = y1 - y0;
let t = ((mx - x0) * dx + (my - y0) * dy) / (dx * dx + dy * dy);
t = Math.max(0,Math.min(1,t));
let x = this.lerp(x0,x1,t);
let y = this.lerp(y0,y1,t);
return ({ x: x,y: y });
}
// draw the scene
draw() {
let ctx = this.canvasElement.getContext('2d');
let cw = this.canvasElement.width;
let ch = this.canvasElement.height;
ctx.clearRect(0,cw,ch);
// draw all lines at their current positions
for (let i = 0; i < this.lines.length; i++) {
this.drawLine(this.lines[i],'black');
}
// draw markers if a line is being dragged
if (this.nearest) {
// point on line this.nearest to mouse
ctx.beginPath();
ctx.arc(this.nearest.pt.x,this.nearest.pt.y,5,Math.PI * 2);
ctx.strokeStyle = 'red';
ctx.stroke();
// marker for original line before dragging
this.drawLine(this.nearest.originalLine,'red');
// hightlight the line as its dragged
this.drawLine(this.nearest.line,'red');
}
}
drawLine(line,color) {
let ctx = this.canvasElement.getContext('2d');
ctx.beginPath();
ctx.moveTo(line.x0,line.y0);
ctx.lineTo(line.x1,line.y1);
ctx.strokeStyle = color;
ctx.stroke();
}
handleMouseDown(e: { preventDefault: () => void; stopPropagation: () => void; clientX: number; clientY: number; }) {
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
// mouse position
this.startX = e.clientX - this.offsetX;
this.startY = e.clientY - this.offsetY;
// find this.nearest line to mouse
this.nearest = this.closestLine(this.startX,this.startY);
this.draw();
// set dragging flag
this.isDown = true;
}
handleMouseUpOut(e) {
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
// clear dragging flag
this.isDown = false;
this.nearest = null;
this.draw();
}
handleMouseMove(e) {
if (!this.isDown) { return; }
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
// mouse position
const mouseX = e.clientX - this.offsetX;
const mouseY = e.clientY - this.offsetY;
// calc how far mouse has moved since last mousemove event
let dx = mouseX - this.startX;
let dy = mouseY - this.startY;
this.startX = mouseX;
this.startY = mouseY;
// change this.nearest line vertices by distance moved
let line = this.nearest.line;
line.x0 += dx;
line.y0 += dy;
line.x1 += dx;
line.y1 += dy;
// redraw
this.draw();
}
}
这是我的HTML文件
<canvas #canvasDraw width=300 height=300></canvas>
我尝试过这样,但是看起来不起作用
<canvas #canvasDraw width=300 height=300 (mousedown)="handleMouseDown($event)" (mousemove)="handleMouseMove($event)"
(mouseup)="handleMouseUpOut($event)" (mouseout)="handleMouseUpOut($event)"></canvas>
解决方法
您忘记确保使用以下方法设置偏移量:reOffset()。 在上面共享的代码中,您根本没有使用该方法,并且代码依赖于正确设置偏移量。
一旦视图被完全初始化,并且由于Ionic的标头不会被完全初始化,不幸的是,即使ngAfterViewInit()也无法帮助捕获实际偏移,应该调用此方法。
所以我使用requestAnimationFrame技巧来确保正确设置偏移量(您也可以使用Promise.resolve或使用setTimeout进行播放):
ngAfterViewInit() {
this.canvasElement = this.canvas.nativeElement;
this.lines = [];
this.lines.push({ x0: 75,y0: 25,x1: 125,y1: 25 });
this.lines.push({ x0: 75,y0: 100,y1: 100 });
this.lines.push({ x0: 50,y0: 35,x1: 50,y1: 85 });
this.lines.push({ x0: 150,x1: 150,y1: 85 });
this.draw();
//this.reOffset();
requestAnimationFrame(()=>{
this.reOffset()
})
}
此处的工作版本:https://stackblitz.com/edit/ionic-angular-v5-twdvkm?file=src/app/app.component.ts
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。