RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1408484
Accepted
dotagenius
dotagenius
Asked:2022-07-10 22:45:32 +0000 UTC2022-07-10 22:45:32 +0000 UTC 2022-07-10 22:45:32 +0000 UTC

如何在画布js中的浮动图像顶部显示文本?

  • 772

在这个问题的答案中,有一个画布中物体移动的例子。
如何在中心显示画布中的文本,以便画布的内容可以像以前一样移动,但文本保持静止?

我放置ctx.font = "48px serif"; ctx.fillText(text, canvas.width / 2, 100);在正方形的输出之后,但由于某种原因,文本附加到它们并移动。

const ctx = canvas.getContext("2d");
canvas.width = 500;
canvas.height = 500;
const rand = (m = 255, M = m + (m = 0)) => (Math.random() * (M - m) + m) | 0;


const objects = [];
for (let i = 0; i < 100; i++) {
  objects.push({x: rand(canvas.width), y: rand(canvas.height),w: rand(40),h: rand(40), col: `rgb(${rand()},${rand()},${rand()})`});
}

requestAnimationFrame(drawCanvas); 

const view = (() => {
  const matrix = [1, 0, 0, 1, 0, 0]; // current view transform
  var m = matrix;             // alias 
  var scale = 1;              // current scale
  var ctx;                    // reference to the 2D context
  const pos = { x: 0, y: 0 }; // current position of origin
  var dirty = true;
  const API = {
    set context(_ctx) { ctx = _ctx; dirty = true },
    apply() {
      if (dirty) { this.update() }
      ctx.setTransform(m[0], m[1], m[2], m[3], m[4], m[5])
    },
    get scale() { return scale },
    get position() { return pos },
    isDirty() { return dirty },
    update() {
      dirty = false;
      m[3] = m[0] = scale;
      m[2] = m[1] = 0;
      m[4] = pos.x;
      m[5] = pos.y;
    },
    pan(amount) {
      if (dirty) { this.update() }
       pos.x += amount.x;
       pos.y += amount.y;
       dirty = true;
    },
    scaleAt(at, amount) { // at in screen coords
      if (dirty) { this.update() }
      scale *= amount;
      pos.x = at.x - (at.x - pos.x) * amount;
      pos.y = at.y - (at.y - pos.y) * amount;
      dirty = true;
    },
  };
  return API;
})();
view.context = ctx;
function drawCanvas() {
    if (view.isDirty()) { 
        ctx.setTransform(1, 0, 0, 1, 0, 0); 
        ctx.clearRect(0, 0, canvas.width, canvas.height);

        view.apply(); // set the 2D context transform to the view
        for (i = 0; i < objects.length; i++) {
            var obj = objects[i];
            ctx.fillStyle = obj.col;
            ctx.fillRect(obj.x, obj.y, obj.h, obj.h);
        }
        ctx.font = "48px serif";
        ctx.fillText("Hello World!", canvas.width / 2, 50);
    }
    requestAnimationFrame(drawCanvas);
}


canvas.addEventListener("mousemove", mouseEvent, {passive: true});
canvas.addEventListener("mousedown", mouseEvent, {passive: true});
canvas.addEventListener("mouseup", mouseEvent, {passive: true});
canvas.addEventListener("mouseout", mouseEvent, {passive: true});
canvas.addEventListener("wheel", mouseWheelEvent, {passive: false});
const mouse = {x: 0, y: 0, oldX: 0, oldY: 0, button: false};
function mouseEvent(event) {
    if (event.type === "mousedown") { mouse.button = true }
    if (event.type === "mouseup" || event.type === "mouseout") { mouse.button = false }
    mouse.oldX = mouse.x;
    mouse.oldY = mouse.y;
    mouse.x = event.offsetX;
    mouse.y = event.offsetY    
    if(mouse.button) { // pan
        view.pan({x: mouse.x - mouse.oldX, y: mouse.y - mouse.oldY});
    }
}
function mouseWheelEvent(event) {
    var x = event.offsetX;
    var y = event.offsetY;
    if (event.deltaY < 0) { view.scaleAt({x, y}, 1.1) }
    else { view.scaleAt({x, y}, 1 / 1.1) }
    event.preventDefault();
}
body {
  background: gainsboro;
  margin: 0;
}
canvas {
  background: white;
  box-shadow: 1px 1px 1px rgba(0, 0, 0, .2);
}
<canvas id="canvas"></canvas>

画布中需要文本,因为我将画布的所有内容保存到图像中。

javascript canvas
  • 1 1 个回答
  • 23 Views

1 个回答

  • Voted
  1. Best Answer
    EzioMercer
    2022-07-10T23:43:02Z2022-07-10T23:43:02Z

    只需在绘制文本之前恢复原始矩阵,使用CanvasRenderingContext2D.resetTransform():

    const ctx = canvas.getContext("2d");
    canvas.width = 500;
    canvas.height = 500;
    const rand = (m = 255, M = m + (m = 0)) => (Math.random() * (M - m) + m) | 0;
    
    
    const objects = [];
    for (let i = 0; i < 100; i++) {
      objects.push({x: rand(canvas.width), y: rand(canvas.height),w: rand(40),h: rand(40), col: `rgb(${rand()},${rand()},${rand()})`});
    }
    
    requestAnimationFrame(drawCanvas); 
    
    const view = (() => {
      const matrix = [1, 0, 0, 1, 0, 0]; // current view transform
      var m = matrix;             // alias 
      var scale = 1;              // current scale
      var ctx;                    // reference to the 2D context
      const pos = { x: 0, y: 0 }; // current position of origin
      var dirty = true;
      const API = {
        set context(_ctx) { ctx = _ctx; dirty = true },
        apply() {
          if (dirty) { this.update() }
          ctx.setTransform(m[0], m[1], m[2], m[3], m[4], m[5])
        },
        get scale() { return scale },
        get position() { return pos },
        isDirty() { return dirty },
        update() {
          dirty = false;
          m[3] = m[0] = scale;
          m[2] = m[1] = 0;
          m[4] = pos.x;
          m[5] = pos.y;
        },
        pan(amount) {
          if (dirty) { this.update() }
           pos.x += amount.x;
           pos.y += amount.y;
           dirty = true;
        },
        scaleAt(at, amount) { // at in screen coords
          if (dirty) { this.update() }
          scale *= amount;
          pos.x = at.x - (at.x - pos.x) * amount;
          pos.y = at.y - (at.y - pos.y) * amount;
          dirty = true;
        },
      };
      return API;
    })();
    view.context = ctx;
    function drawCanvas() {
        if (view.isDirty()) { 
            ctx.setTransform(1, 0, 0, 1, 0, 0); 
            ctx.clearRect(0, 0, canvas.width, canvas.height);
    
            view.apply(); // set the 2D context transform to the view
            for (i = 0; i < objects.length; i++) {
                var obj = objects[i];
                ctx.fillStyle = obj.col;
                ctx.fillRect(obj.x, obj.y, obj.h, obj.h);
            }
            ctx.resetTransform();
            ctx.font = "48px serif";
            ctx.fillText("Hello World!", canvas.width / 2, 50);
        }
        requestAnimationFrame(drawCanvas);
    }
    
    
    canvas.addEventListener("mousemove", mouseEvent, {passive: true});
    canvas.addEventListener("mousedown", mouseEvent, {passive: true});
    canvas.addEventListener("mouseup", mouseEvent, {passive: true});
    canvas.addEventListener("mouseout", mouseEvent, {passive: true});
    canvas.addEventListener("wheel", mouseWheelEvent, {passive: false});
    const mouse = {x: 0, y: 0, oldX: 0, oldY: 0, button: false};
    function mouseEvent(event) {
        if (event.type === "mousedown") { mouse.button = true }
        if (event.type === "mouseup" || event.type === "mouseout") { mouse.button = false }
        mouse.oldX = mouse.x;
        mouse.oldY = mouse.y;
        mouse.x = event.offsetX;
        mouse.y = event.offsetY    
        if(mouse.button) { // pan
            view.pan({x: mouse.x - mouse.oldX, y: mouse.y - mouse.oldY});
        }
    }
    function mouseWheelEvent(event) {
        var x = event.offsetX;
        var y = event.offsetY;
        if (event.deltaY < 0) { view.scaleAt({x, y}, 1.1) }
        else { view.scaleAt({x, y}, 1 / 1.1) }
        event.preventDefault();
    }
    body {
      background: gainsboro;
      margin: 0;
    }
    canvas {
      background: white;
      box-shadow: 1px 1px 1px rgba(0, 0, 0, .2);
    }
    <canvas id="canvas"></canvas>

    • 2

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5