我需要捕获哪个事件才能在使用 Vue 鼠标按下时捕获鼠标移动
Which event do I need to capture to catching a mouse move while mousedown with Vue
我正在使用 Vue3 构建一个带有自上而下地图的 2D 游戏。我创建了一个简单的地图编辑器,您可以在其中将每个图块从一个集合拖到地图上。对于大地图来说,这会变得非常麻烦,因此我想尝试另一种方式。我的想法就像一个绘图工具,你select把“画笔”拖到“canvas”上。唯一的问题是,地图是由 div
排列成矩阵的图块构建的。我尝试了以下方法,但由于某种原因绘图被延迟并且它在其他图块上生成“工件”(我开始拖动图块 20:4 但图块 15:2 也更新了。
<div class="tiles">
<div v-for="(row, y) in tiles" class="row"
:key="'row_' + y"
:style="{width: mapSize.x + 'px'}">
<div v-for="(tile, x) in row" class="tile"
:class="tile.background"
:key="'tile_' + x + '_' + y"
@dragover.prevent
@dragenter="onDragEnter(x, y)">
</div>
</div>
</div>
我没有可拖动的元素,也许这就是问题所在,但我还可以使用什么其他事件来进行点击移动?
我建议您使用 mousedown
、mousemove
和 mouseup
以及它们的触摸 semi-equivalents(如果使用触摸设备)。
这是一个示例,代码中有注释。
const colors = ["powderblue","gold","orangered","deeppink", "deepskyblue","palegreen"];
const generateTiles = (wx, wy) => {
const ret = [];
for (let y = 0; y < wy; y++) {
const row = [];
ret.push(row)
for (let x = 0; x < wx; x++) {
row.push({x,y,background: colors[0]})
}
}
return ret;
}
Vue.createApp({
el: '#app',
setup() {
const tiles = Vue.reactive(generateTiles(10,10)); // setup tiles and make reactive
const color = Vue.ref(1); // helper for managing color(s)
let mouseDown = false; // no need to make reactive
// do some stuff to the tile here
const setTileBg = (tile) => {
tile.background=colors[color.value];
}
const handlers = {
// reuse handler, used both for parent and
onMouseDown: (tile) => {
mouseDown = true;
if(tile) setTileBg(tile);
},
onMouseUp: (e) => {
mouseDown = false;
},
onMouseOver: (tile) => {
if(mouseDown) setTileBg(tile);
}
}
// adding it to window (instead of an element) allows
// capturing mouseup event even when mouse is not within
// the dom element
window.addEventListener('mouseup', handlers.onMouseUp)
return {
tiles, color, colors, ...handlers
}
}
}).mount('#app')
.tiles,select{width:200px;margin:0 auto;display:block}.tile{display:inline-block;width:20px;height:20px;border:1px solid #000;box-sizing:border-box;font-size:10px;font-family:monospace;cursor:pointer;color:rgba(0,0,0,.4);text-align:center;padding:3px}.row{display:block;height:20px;width:200px;box-sizing:content-box;user-select:none}
<script src="https://unpkg.com/vue@3.0.2/dist/vue.global.prod.js"></script>
<div id="app">
<div>
<select v-model="color">
<option :value="i" v-for="(c,i) in colors" :style="{'background-color':c}">{{c}}</option>
</select>
</div>
<div class="tiles">
<div v-for="(row, y) in tiles" class="row"
:key="'row_' + y"
>
<div v-for="(tile, x) in row" class="tile"
:style="{'background-color':tile.background}"
:key="'tile_' + x + '_' + y"
@mouseDown="onMouseDown(tile)"
@mouseOver="onMouseOver(tile)">
{{ y * row.length + x}}
</div>
</div>
</div>
</div>
我正在使用 Vue3 构建一个带有自上而下地图的 2D 游戏。我创建了一个简单的地图编辑器,您可以在其中将每个图块从一个集合拖到地图上。对于大地图来说,这会变得非常麻烦,因此我想尝试另一种方式。我的想法就像一个绘图工具,你select把“画笔”拖到“canvas”上。唯一的问题是,地图是由 div
排列成矩阵的图块构建的。我尝试了以下方法,但由于某种原因绘图被延迟并且它在其他图块上生成“工件”(我开始拖动图块 20:4 但图块 15:2 也更新了。
<div class="tiles">
<div v-for="(row, y) in tiles" class="row"
:key="'row_' + y"
:style="{width: mapSize.x + 'px'}">
<div v-for="(tile, x) in row" class="tile"
:class="tile.background"
:key="'tile_' + x + '_' + y"
@dragover.prevent
@dragenter="onDragEnter(x, y)">
</div>
</div>
</div>
我没有可拖动的元素,也许这就是问题所在,但我还可以使用什么其他事件来进行点击移动?
我建议您使用 mousedown
、mousemove
和 mouseup
以及它们的触摸 semi-equivalents(如果使用触摸设备)。
这是一个示例,代码中有注释。
const colors = ["powderblue","gold","orangered","deeppink", "deepskyblue","palegreen"];
const generateTiles = (wx, wy) => {
const ret = [];
for (let y = 0; y < wy; y++) {
const row = [];
ret.push(row)
for (let x = 0; x < wx; x++) {
row.push({x,y,background: colors[0]})
}
}
return ret;
}
Vue.createApp({
el: '#app',
setup() {
const tiles = Vue.reactive(generateTiles(10,10)); // setup tiles and make reactive
const color = Vue.ref(1); // helper for managing color(s)
let mouseDown = false; // no need to make reactive
// do some stuff to the tile here
const setTileBg = (tile) => {
tile.background=colors[color.value];
}
const handlers = {
// reuse handler, used both for parent and
onMouseDown: (tile) => {
mouseDown = true;
if(tile) setTileBg(tile);
},
onMouseUp: (e) => {
mouseDown = false;
},
onMouseOver: (tile) => {
if(mouseDown) setTileBg(tile);
}
}
// adding it to window (instead of an element) allows
// capturing mouseup event even when mouse is not within
// the dom element
window.addEventListener('mouseup', handlers.onMouseUp)
return {
tiles, color, colors, ...handlers
}
}
}).mount('#app')
.tiles,select{width:200px;margin:0 auto;display:block}.tile{display:inline-block;width:20px;height:20px;border:1px solid #000;box-sizing:border-box;font-size:10px;font-family:monospace;cursor:pointer;color:rgba(0,0,0,.4);text-align:center;padding:3px}.row{display:block;height:20px;width:200px;box-sizing:content-box;user-select:none}
<script src="https://unpkg.com/vue@3.0.2/dist/vue.global.prod.js"></script>
<div id="app">
<div>
<select v-model="color">
<option :value="i" v-for="(c,i) in colors" :style="{'background-color':c}">{{c}}</option>
</select>
</div>
<div class="tiles">
<div v-for="(row, y) in tiles" class="row"
:key="'row_' + y"
>
<div v-for="(tile, x) in row" class="tile"
:style="{'background-color':tile.background}"
:key="'tile_' + x + '_' + y"
@mouseDown="onMouseDown(tile)"
@mouseOver="onMouseOver(tile)">
{{ y * row.length + x}}
</div>
</div>
</div>
</div>