Как исправить размытый текст на моем холсте HTML5?
Я в общей сумме n00b С HTML5 и я работаю с canvas для визуализации фигур, цветов и текста. В моем приложении, у меня есть посмотреть адаптер это создает холст динамически и заполняет его содержимым. Это работает очень хорошо, за исключением того, что мой текст отображается очень нечетким/размытым/растянутым. Я видел много других сообщений о том, почему определение ширина и высота на CSS вызовет эту проблему, но я определяю все это в javascript.
соответствующий код (view Скрипка):
HTML
<div id="layout-content"></div>
Javascript
var width = 500;//FIXME:size.w;
var height = 500;//FIXME:size.h;
var canvas = document.createElement("canvas");
//canvas.className="singleUserCanvas";
canvas.width=width;
canvas.height=height;
canvas.border = "3px solid #999999";
canvas.bgcolor = "#999999";
canvas.margin = "(0, 2%, 0, 2%)";
var context = canvas.getContext("2d");
//////////////////
//// SHAPES ////
//////////////////
var left = 0;
//draw zone 1 rect
context.fillStyle = "#8bacbe";
context.fillRect(0, (canvas.height*5/6)+1, canvas.width*1.5/8.5, canvas.height*1/6);
left = left + canvas.width*1.5/8.5;
//draw zone 2 rect
context.fillStyle = "#ffe381";
context.fillRect(left+1, (canvas.height*5/6)+1, canvas.width*2.75/8.5, canvas.height*1/6);
left = left + canvas.width*2.75/8.5 + 1;
//draw zone 3 rect
context.fillStyle = "#fbbd36";
context.fillRect(left+1, (canvas.height*5/6)+1, canvas.width*1.25/8.5, canvas.height*1/6);
left = left + canvas.width*1.25/8.5;
//draw target zone rect
context.fillStyle = "#004880";
context.fillRect(left+1, (canvas.height*5/6)+1, canvas.width*0.25/8.5, canvas.height*1/6);
left = left + canvas.width*0.25/8.5;
//draw zone 4 rect
context.fillStyle = "#f8961d";
context.fillRect(left+1, (canvas.height*5/6)+1, canvas.width*1.25/8.5, canvas.height*1/6);
left = left + canvas.width*1.25/8.5 + 1;
//draw zone 5 rect
context.fillStyle = "#8a1002";
context.fillRect(left+1, (canvas.height*5/6)+1, canvas.width-left, canvas.height*1/6);
////////////////
//// TEXT ////
////////////////
//user name
context.fillStyle = "black";
context.font = "bold 18px sans-serif";
context.textAlign = 'right';
context.fillText("User Name", canvas.width, canvas.height*.05);
//AT:
context.font = "bold 12px sans-serif";
context.fillText("AT: 140", canvas.width, canvas.height*.1);
//AB:
context.fillText("AB: 94", canvas.width, canvas.height*.15);
//this part is done after the callback from the view adapter, but is relevant here to add the view back into the layout.
var parent = document.getElementById("layout-content");
parent.appendChild(canvas);
результаты, которые я вижу (в сафари) гораздо более перекошены, чем показано на скрипке:
шахты

Скрипка

что я делаю неправильно? Я нужен отдельный холст для каждого элемента текста? Это шрифт? Требуется ли мне сначала определить холст в макете HTML5? Есть ли опечатка? Я заблудился.
6 ответов:
элемент canvas работает независимо от соотношения пикселей устройства или монитора.
на iPad 3+ это соотношение равно 2. Это по существу означает, что ваш холст шириной 1000 пикселей теперь должен будет заполнить 2000 пикселей, чтобы соответствовать заявленной ширине на дисплее iPad. К счастью для нас, это делается автоматически браузером. С другой стороны, это также причина, по которой вы видите меньше определения на изображениях и элементах холста, которые были сделаны, чтобы непосредственно соответствовать их видимой области. Потому что ваш холст знает только, как заполнить 1000px, но его просят нарисовать до 2000px, теперь браузер должен разумно заполнить пробелы между пикселями, чтобы отобразить элемент в его правильном размере.
Я настоятельно рекомендую вам прочитать в этой статье С HTML5Rocks что более подробно объясняет, как создавать элементы высокой четкости.
tl; dr? Вот пример (на основе выше тут), который я использую в своих проектах, чтобы выплюнуть холст с правильное разрешение:
var PIXEL_RATIO = (function () { var ctx = document.createElement("canvas").getContext("2d"), dpr = window.devicePixelRatio || 1, bsr = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1; return dpr / bsr; })(); createHiDPICanvas = function(w, h, ratio) { if (!ratio) { ratio = PIXEL_RATIO; } 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); return can; } //Create canvas with the device resolution. var myCanvas = createHiDPICanvas(500, 250); //Create canvas with a custom resolution. var myCustomCanvas = createHiDPICanvas(500, 200, 4);надеюсь, что это помогает!
решена!
Я решил посмотреть, что изменение ширина и высота атрибуты, которые я установил в
javascriptчтобы увидеть, как это повлияло на размер холста-и это не. Он меняет разрешение.чтобы получить результат, я хотел, я также должен был установить
canvas.style.widthатрибут, который изменяет физический размерcanvas:canvas.width=1000;//horizontal resolution (?) - increase for better looking text canvas.height=500;//vertical resolution (?) - increase for better looking text canvas.style.width=width;//actual width of canvas canvas.style.height=height;//actual height of canvas
Я изменяю размер элемента canvas с помощью css, чтобы взять всю ширину родительского элемента. Я заметил, что ширина и высота моего элемента не масштабируется. Я искал лучший способ установить размер, который должен быть.
canvas.width = canvas.clientWidth; canvas.height = canvas.clientHeight;этот простой способ ваш холст будет установлен, независимо от того, какой экран вы будете использовать.
Это 100% решил его для меня:
var canvas = document.getElementById('canvas'); canvas.width = canvas.getBoundingClientRect().width; canvas.height = canvas.getBoundingClientRect().height;(это близко к решению Адама Маньковского).
Я немного адаптировал MyNameIsKo код canvg (SVG в библиотеку Canvas js). Я был смущен на некоторое время и потратить некоторое время на это. Надеюсь, это поможет кому-то.
HTML
<div id="chart"><canvas></canvas><svg>Your SVG here</svg></div>Javascript
window.onload = function() { var PIXEL_RATIO = (function () { var ctx = document.createElement("canvas").getContext("2d"), dpr = window.devicePixelRatio || 1, bsr = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1; return dpr / bsr; })(); setHiDPICanvas = function(canvas, w, h, ratio) { if (!ratio) { ratio = PIXEL_RATIO; } var can = 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); } var svg = document.querySelector('#chart svg'), canvas = document.querySelector('#chart canvas'); var svgSize = svg.getBoundingClientRect(); var w = svgSize.width, h = svgSize.height; setHiDPICanvas(canvas, w, h); var svgString = (new XMLSerializer).serializeToString(svg); var ctx = canvas.getContext('2d'); ctx.drawSvg(svgString, 0, 0, w, h); }
для тех из вас, кто работает в reactjs, я адаптировал ответ MyNameIsKo, и он отлично работает. Вот этот код.
import React from 'react' export default class CanvasComponent extends React.Component { constructor(props) { this.calcRatio = this.calcRatio.bind(this); } // Use componentDidMount to draw on the canvas componentDidMount() { this.updateChart(); } calcRatio() { let ctx = document.createElement("canvas").getContext("2d"), dpr = window.devicePixelRatio || 1, bsr = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1; return dpr / bsr; } // Draw on the canvas updateChart() { // Adjust resolution const ratio = this.calcRatio(); this.canvas.width = this.props.width * ratio; this.canvas.height = this.props.height * ratio; this.canvas.style.width = this.props.width + "px"; this.canvas.style.height = this.props.height + "px"; this.canvas.getContext("2d").setTransform(ratio, 0, 0, ratio, 0, 0); const ctx = this.canvas.getContext('2d'); // now use ctx to draw on the canvas } render() { return ( <canvas ref={el=>this.canvas=el} width={this.props.width} height {this.props.height}/> ) } }в этом примере я передаю ширину и высоту холста в качестве реквизита.
Comments