首页 > 解决方案 > 如何使高 DPI 画布变得灵活?

问题描述

我做了一个 js High DPI Canvas。但是如果我让窗口更小(浏览器窗口,因为它是从浏览器窗口计算的,而不是在 chrome 开发工具中) - 它超出了我设置的初始宽度和高度,它会改变它的宽度和高度,所以看不到左边或\和下边界。我怎样才能在不丢失部分画布的情况下制作可以适应较小尺寸的高 DPI 柔性画布?

 // get pixel ratio
var PIXEL_RATIO = function () {
  var ctx = document.createElement("canvas").getContext("2d");
  var dpr = window.devicePixelRatio || 1;
  var bsr = ctx.webkitBackingStorePixelRatio ||
            ctx.mozBackingStorePixelRatio ||
            ctx.msBackingStorePixelRatio ||
            ctx.oBackingStorePixelRatio ||
            ctx.backingStorePixelRatio || 1;

  return dpr / bsr;
};

// create such a canvas that is not blured on any display size  
var createHiDPICanvas = function(w, h, ratio) {
  if (!ratio) { ratio = PIXEL_RATIO(); }
  var chart_container = document.getElementById("lifespan-chart-content");
  var can = document.createElement("canvas");
  can.width = w * ratio;
  can.height = h * ratio;
  can.style.width = w + "px";
  can.style.height = h + "px";
  can.getContext("2d").setTransform(ratio, 0, 0, ratio, 0, 0);
  chart_container.appendChild(can);
  return can;
}

// height and width of the canvas
var w    = 500; // should be flexible
var h    = 320;  // should be constant
var text = "Center";
var font = "18px Arial"
var border_width = 50;

//Create canvas & context
canvas = createHiDPICanvas(w, h);
ctx = canvas.getContext("2d");

// create a text
var middle = {x : canvas.width/2, y : canvas.height/2};
var text_width = ctx.measureText(text).width;
ctx.font = font;
ctx.moveTo(middle.x, middle.y);
ctx.fillText("Center", middle.x - text_width / 2, middle.y);

// create left and down borders
createBorders(border_width);

function createBorders(border_width) {
  ctx.save();
  var canv_height = canvas.height;
  var canv_width = canvas.width;
  ctx.moveTo(0,0);
  ctx.lineTo(border_width, 0);
  ctx.lineTo(border_width, canv_height - border_width);
  ctx.lineTo(canv_width, canv_height - border_width);
  ctx.lineTo(canv_width, canv_height);
  ctx.lineTo(0, canv_height);
  ctx.lineTo(0, 0);
  ctx.fill = "black";
  ctx.stroke();
  ctx.restore();
}
canvas {
    background-color:bisque;
}
#lifespan-chart {
    display: flex;
    justify-content: center;
}
#lifespan-chart-content {
    overflow: scroll;
}
<div id="lifespan-chart">
    <div id="lifespan-chart-content"></div>
</div>

PS好的。添加overflow:scroll;到带有画布的容器上,现在只有左侧部分可见。如果用户希望他可以向右滚动,但是有什么方法可以在这种情况下使左侧可见并且在没有 X 滚动的情况下隐藏右侧溢出(如果我的问题没有答案)?

编辑 1

回答我的 PS 问题:我需要添加overflow:hidden,如果尺寸较小,它将不会显示画布的中心部分。它将从左侧部分开始并隐藏右侧部分。考虑到用户能够(在实际项目画布中)滚动画布 - 它可以向右移动并查看所有隐藏的对象

但这不是主要的按比例灵活的画布问题的答案

标签: javascript

解决方案


我认为您ratio几乎需要在任何地方使用,例如:

// get pixel ratio
var PIXEL_RATIO = function () {
  var ctx = document.createElement("canvas").getContext("2d");
  var dpr = window.devicePixelRatio || 1;
  var bsr = ctx.webkitBackingStorePixelRatio ||
            ctx.mozBackingStorePixelRatio ||
            ctx.msBackingStorePixelRatio ||
            ctx.oBackingStorePixelRatio ||
            ctx.backingStorePixelRatio || 1;

  return dpr / bsr;
};

// create such a canvas that is not blured on any display size  
var createHiDPICanvas = function(w, h, ratio) {
  var chart_container = document.getElementById("lifespan-chart-content");
  var can = document.createElement("canvas");
  can.width = w * ratio;
  can.height = h * ratio;
  can.style.width = w + "px";
  can.style.height = h + "px";
  can.getContext("2d").setTransform(ratio, 0, 0, ratio, 0, 0);
  chart_container.appendChild(can);
  return can;
}

// height and width of the canvas
var w    = 500; // should be flexible
var h    = 320;  // should be constant
var text = "Center";
var font = "18px Arial"
var border_width = 50;
var ratio = PIXEL_RATIO();

//Create canvas & context
canvas = createHiDPICanvas(w, h, ratio);
ctx = canvas.getContext("2d");

// create a text
var middle = {x : canvas.width / ratio / 2, y : canvas.height / ratio / 2};
var text_width = ctx.measureText(text).width / ratio;
ctx.font = font;
ctx.moveTo(middle.x, middle.y);
ctx.fillText("Center", middle.x - text_width / 2, middle.y);

// create left and down borders
createBorders(border_width);

function createBorders(border_width) {
  ctx.save();
  var canv_height = canvas.height / ratio;
  var canv_width = canvas.width / ratio;
  ctx.moveTo(0,0);
  ctx.lineTo(border_width, 0);
  ctx.lineTo(border_width, canv_height - border_width);
  ctx.lineTo(canv_width, canv_height - border_width);
  ctx.lineTo(canv_width, canv_height);
  ctx.lineTo(0, canv_height);
  ctx.lineTo(0, 0);
  ctx.fill = "black";
  ctx.stroke();
  ctx.restore();
}

推荐阅读