平滑拖动等轴测图 - Html5

时间:2012-08-30 10:10:04

标签: html coffeescript isometric

我已经实现了一个基本的Isometric tile引擎,可以通过用鼠标拖动地图来探索它。请看下面的小提琴并拖走:

http://jsfiddle.net/kHydg/14/

细分的代码是(CoffeeScript):

绘制功能

draw = ->
  requestAnimFrame draw
  canvas.width = canvas.width

  for row in [0..width]
    for col in [0..height]
      xpos = (row - col) * tileHeight + width
      xpos += (canvas.width / 2) - (tileWidth / 2) + scrollPosition.x
      ypos = (row + col) * (tileHeight / 2) + height + scrollPosition.y
      context.drawImage(defaultTile, Math.round(xpos), Math.round(ypos), tileWidth, tileHeight)

鼠标拖动滚动控件

scrollPosition =
  x: 0
  y: 0

dragHelper = 
  active: false
  x: 0
  y: 0


window.addEventListener 'mousedown', (e) =>
  handleMouseDown(e)
, false

window.addEventListener 'mousemove', (e) =>
  handleDrag(e)
, false

window.addEventListener 'mouseup', (e) =>
  handleMouseUp(e)
, false

handleDrag = (e) =>
  e.preventDefault()
  if dragHelper.active
    x = e.clientX
    y = e.clientY
    scrollPosition.x -= Math.round((dragHelper.x - x) / 28)
    scrollPosition.y -= Math.round((dragHelper.y - y) / 28)

handleMouseUp = (e) =>
  e.preventDefault()
  dragHelper.active = false

handleMouseDown = (e) =>
  e.preventDefault()
  x = e.clientX
  y = e.clientY
  dragHelper.active = true
  dragHelper.x = x
  dragHelper.y = y

问题

正如你从小提琴中看到的那样,拖动动作还可以,但并不完美。如何更改代码以使拖动操作更顺畅?我想要的是你拖动时点击以保持在鼠标点下方的地图点;和他们在这里做的一样:http://craftyjs.com/demos/isometric/

1 个答案:

答案 0 :(得分:1)

很多图书馆帮助这样的事情。我建议使用d3的数据处理功能来帮助,原因有几个。

首先,在d3中,存在拖动行为,其中存储对象的原点并且在拖动开始时计算相对于原点的鼠标位置。然后,您可以使用鼠标的绝对位置来确定对象应该在哪里,并避免使用相对更改时出现的增量错误 - 如上所述,当您开始舍入时会更糟糕。

dragMap = (d) ->  
  d.x = d3.event.x # d3.event.x, y are computed relative to the origin for you!
  d.y = d3.event.y 

dragBehavior = d3.behavior.drag()
  .origin(Object) # equivalent to (d) -> d 
  .on("drag", dragMap)

d3.select(canvas)
  .datum(x: 0, y: 0)  # Load your canvas with an arbitary origin
  .call(dragBehavior) # And now you can drag it!

其次,通过使用d3的线性或其他数字刻度,您可以避免自己进行典型的绘图数学,这很容易出错,尤其是当您必须在整个地方进行时。在您将拖动缩放到28之前。在我当前的方法中,这是不必要的,但如果您将绘图算法更改为使用切片而不是像素,则可以更改此比例,这将自动将鼠标像素转换为切片大小。

pixelToTile = d3.scale.linear()
  .domain([0, 1])
  .range([0, 1])  

这是你用d3帮助完成的小提琴。没有dragHelper和所有必要的无关代码。所有Math.round调用都是不必要的,除了用于画布绘制的调用,它会阻止抗锯齿。

http://jsfiddle.net/kHydg/23/

是不是更短更甜?

P.S。等距实时浏览器游戏是一个很棒的主意。我有空的时候一定会尝试制作一个。