【问题标题】:Render a x-axis on a HTML canvas, that adapts when user pans on the canvas在 HTML 画布上渲染 x 轴,当用户在画布上平移时会适应
【发布时间】:2018-06-26 15:38:42
【问题描述】:

我想在 HTML canvas 上渲染一个时间 x 轴,当我平移(通过单击+拖动)或缩放时进行调整。

可能存在图表 JS 库来为曲线/图表执行此操作,但在我的情况下,x 轴上的数据不会是曲线,所以我需要从头开始。

在这里,当我在背景上单击+拖动时,原点x 会适应,这很好(参见 sn-p)。 但是如何在canvas的底部呈现这样的文本x轴呢?

--------------------------------------------------
|           |           |            |           |
jan 02      jan 03      jan 04       jan 05      jan 06

var drag = false;
var x = 0;
var last_position = {};

document.getElementById('canvas').onmousedown = function() { drag = true; }
document.getElementById('canvas').onmouseup = function() { drag = false; }
document.getElementById('canvas').onmousemove = function(e) { 
  var deltaX = last_position.x - e.clientX,
      deltaY = last_position.y - e.clientY;
  if (drag && typeof(last_position.x) != 'undefined') { 
    x += deltaX;
    document.getElementById('pos').innerHTML = x; 
  } 
  last_position = { x : e.clientX, y : e.clientY };  
}
#canvas { width: 400px; height: 150px; background-color: #ccc; }
<canvas id="canvas"></canvas>
<div id="pos"></div>

【问题讨论】:

    标签: javascript html canvas


    【解决方案1】:

    您需要做的就是从所需的屏幕坐标中减去 x 位置,请参见下面的示例。

    /* 
     * Your original code: 
     */
    var drag = false;
    var x = 0;
    var last_position = {};
    
    document.getElementById('canvas').onmousedown = function() { drag = true; }
    document.getElementById('canvas').onmouseup = function() { drag = false; }
    document.getElementById('canvas').onmousemove = function(e) { 
      var deltaX = last_position.x - e.clientX,
          deltaY = last_position.y - e.clientY;
      if (drag && typeof(last_position.x) != 'undefined') { 
        x += deltaX;
        document.getElementById('pos').innerHTML = x; 
      } 
      last_position = { x : e.clientX, y : e.clientY };
    }
    
    /*
     * A simple draw text method:
     */
    function drawText(context, text, x, y) {
      context.font = "12px Arial";
      context.fillStyle = "red";
      context.textAlign = "center";
      context.fillText(text, x, y);
    }
    
    /*
     * The below uses 'requestAnimationFrame' to run a rendering loop:
     * For more information see https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame 
     */
    function render() {
    
      var canvas = document.getElementById('canvas')
      var context = canvas.getContext("2d");
    
      /* We must clear the canvas before rendering anything else... */
      context.clearRect(0, 0, canvas.width, canvas.height);
    
      /* This could be improved a fair bit, consider using a loop / non magic numbers. */
      drawText(context, "Jan 1st", 30 - x, canvas.height - 12);
      drawText(context, "Jan 2nd", 100 - x, canvas.height - 12);
      drawText(context, "Jan 3rd", 170 - x, canvas.height - 12);
      drawText(context, "Jan 4th", 240 - x, canvas.height - 12);
      drawText(context, "Jan 5th", 310 - x, canvas.height - 12);
    
      requestAnimationFrame(render);
    }
    render();
    #canvas { width: 400px; height: 150px; background-color: #ccc; }
    <canvas id="canvas"></canvas>
    <div id="pos">0</div>

    请注意,这可以在效率和清洁度方面得到相当大的改善 - 即您不应该渲染屏幕外的文本。

    【讨论】:

    • 非常感谢!就是这个主意!事实上,我希望它是一个无限的 x 轴,即动态添加新日期(我应该在问题中添加这个),你会怎么做?
    • 这是一个非常不同的问题,其目的是在主要帖子中。我建议您为此创建一个新帖子。
    • 我刚刚发布了一个答案(受您的启发)@JacobPersi:stackoverflow.com/a/48309378/1422096
    【解决方案2】:

    根据 JacobPersi 的回答(99.9% 归功于他),这是一个解决方案:

    function formatDate(date) {
      var monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
      var day = date.getDate(), monthIndex = date.getMonth(), year = date.getFullYear().toString().substr(-2);
      return day + ' ' + monthNames[monthIndex] + ' ' + year;
    }
    
    var drag = false;
    var x = 0;
    var last_position = {};
    
    var canvas = document.getElementById('canvas');
    canvas.width = canvas.getBoundingClientRect().width;  // important to prevent blurry text issues: https://stackoverflow.com/q/15661339/1422096
    canvas.height = canvas.getBoundingClientRect().height;
    canvas.onmousedown = function() { drag = true; }
    document.onmouseup = function() { drag = false; }
    canvas.onmousemove = function(e) { 
      var deltaX = last_position.x - e.clientX,
          deltaY = last_position.y - e.clientY;
      if (drag && typeof(last_position.x) != 'undefined') { 
        x += deltaX;
      } 
      last_position = { x : e.clientX, y : e.clientY };
    }
    
    function drawText(context, text, x, y) {
      context.font = "10px Arial";
      context.fillStyle = "black";
      context.textAlign = "center";
      context.fillText(text, x, y);
    }
    
    function render() {
    
      var canvas = document.getElementById('canvas')
      var context = canvas.getContext("2d");
    
      context.clearRect(0, 0, canvas.width, canvas.height);
    
      for (var i = Math.round((-2000+x)/200); 200 * i - x < 2000; i++) {
          var d = new Date();
          d.setTime(d.getTime() + i * 3600 * 24 * 1000);
          var s = formatDate(d);       
          drawText(context, s, 200 * i - x, canvas.height - 8);
      }
      requestAnimationFrame(render);
    }
    render();
    * { margin: 0; padding: 0; border: 0; }
    body, html { height: 100% }
    #canvas { width: 100%; height: 75%; background-color: #ccc; }
    #canvas2 { width: 100%; height: 25%; background-color: #aaa; }
    <canvas id="canvas"></canvas>
    <canvas id="canvas2"></canvas>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-07
      • 1970-01-01
      • 2021-05-27
      • 1970-01-01
      • 1970-01-01
      • 2017-04-26
      • 2011-02-20
      • 2012-07-13
      相关资源
      最近更新 更多