javascript - 如何通过在 html5/canvas 中拖动背景来移动对象?
问题描述
我希望能够通过拖动它来创建一个可移动的画布,但能够将对象放置到画布上,这些对象将相对于它们放置的位置保持在原位。我该怎么做呢?
例如,我将 4 张图像放在画布上的不同位置。然后我在画布上的空白处拖动,所有对象都根据鼠标的移动而移动。创建画布具有无限空间的错觉(因为我希望能够在屏幕显示的范围之外放置多个对象)。
我是否必须跟踪对象本身,当我拖动一个空白空间时,让所有对象移动?如果我在画布上说几百个所说的对象(不在视野中但能够使用这种拖动方法重新回到视野中),这将如何影响记忆?
解决方案
主要思想是我相对于鼠标移动翻译画布上下文。请阅读代码中的注释。
在这个例子中,我画了一些圆圈。你可以画任何东西。
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
let cw = canvas.width = window.innerWidth,
cx = cw / 2;
let ch = canvas.height = window.innerHeight,
cy = ch / 2;
//the mouse
let m = {x:0,y:0};//mouse coords on mouse down
let last_m = {x:0,y:0}//mouse coords on dragging
//distance
let d = {x:0,y:0};// distance while dragging
let D = {x:0,y:0};// distance on mouse up
// draw some circles
let circles = [];
let dragging = false;
function drawCircle(color){
let o = {}
o.x = (1 - Math.random() )* 3 * cw;
o.y = Math.random() * ch;
o.r = (Math.random() * 20) + 10;
o.color = color;
o.draw = function(){
ctx.fillStyle = o.color;
ctx.beginPath();
ctx.arc(o.x,o.y,o.r,0,2*Math.PI);
ctx.fill();
}
circles.push(o)
}
for(let i = 0; i < 70; i++){
drawCircle(`hsl(${i * 12},80%,60%)`)
}
for(let i = 0; i < circles.length; i++){circles[i].draw()}
//events
canvas.addEventListener("mousedown",(evt)=>{
dragging = true;
//the mouse position
m = oMousePos(canvas, evt);
})
canvas.addEventListener("mouseup",(evt)=>{
dragging = false;
last_m = oMousePos(canvas, evt);
d.x = last_m.x - m.x;
d.y = last_m.y - m.y;
// the total dragged distance on mouse up
D.x += d.x;
D.y += d.y;
})
canvas.addEventListener("mousemove",(evt)=>{
if(dragging){
last_m = oMousePos(canvas, evt);
d.x = last_m.x - m.x + D.x;
d.y = last_m.y - m.y + D.y;
// clear the context
ctx.clearRect(-cw,0, 2*cw,ch);
ctx.save();
//translate the context
ctx.translate(d.x, d.y);
//repaint everithing
for(let i = 0; i < circles.length; i++){circles[i].draw()}
ctx.restore()
}
})
// a function to detect the mouse position on the canvas
function oMousePos(canvas, evt) {
var ClientRect = canvas.getBoundingClientRect();
return { //objeto
x: Math.round(evt.clientX - ClientRect.left),
y: Math.round(evt.clientY - ClientRect.top)
}
}
*{margin:0;padding:0;}
body {
overflow: hidden;
}
canvas {
background-color: #000;
}
<canvas id="canvas"></canvas>
推荐阅读
- ios - 使用 iOS 应用程序获取 WebClip/设备管理器信息
- git - Visual Studio Code - 显示文件的挂起更改
- flutter - 如何从 Flutter 中的 url 裁剪和下载图像?
- java - 如何缩短 xpath 元素
- java - 无法从 SOAP Web 服务打印 XML 响应
- android - android: ScrollView 切掉顶部
- python - 在 Python 中将字典转换为 DataFrame 的问题
- browserify - 如何对browserify做有条件的要求?
- javascript - 等待 Promise 的结果返回一个承诺?
- angular - 使用 mat 表单字段显示字段