HTML5 tuvalimdeki bulanık metni nasıl düzeltirim?


89

Ben toplam duyuyorum n00b ile HTML5ve ile çalışıyorum canvasşekiller, renkler ve metin oluşturmak için. Uygulamamda, dinamik olarak bir tuval oluşturan ve onu içerikle dolduran bir görünüm bağdaştırıcım var. Metnimin çok bulanık / bulanık / uzatılmış olması dışında bu gerçekten güzel çalışıyor. Ben tanımlayan neden diğer mesajların çok gördük genişlik ve yüksekliğini de CSSbu soruna neden olur, ama ben bunu bütün tanımlar javascript.

İlgili kod ( Fiddle'ı görüntüleyin ):

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);
<div id="layout-content"></div>

Gördüğüm sonuçlar ( Safari'de ) Fiddle'da gösterilenden çok daha çarpık:

Benim

Safari'de işlenmiş çıktı

Vaktini boşa harcamak

JSFiddle üzerinde işlenmiş çıktı

Yanlış olarak ne yapıyorum? Her metin öğesi için ayrı bir tuvale ihtiyacım var mı? Yazı tipi mi? Önce tuvali HTML5 düzeninde tanımlamam gerekir mi? Bir yazım hatası var mı? Ben kayboldum


Aramıyor gibisin clearRect.
David

1
Bu polyfill, HiDPI tarayıcıları ile otomatik olarak yükseltme yapmayan (şu anda sadece safari) en temel tuval işlemlerini düzeltir ... github.com/jondavidjohn/hidpi-canvas-polyfill
jondavidjohn

DIV mozaiği ile tuval bulanıklığı sorununu çözen bir JS çerçevesi geliştiriyorum. Mem
Gonki

Yanıtlar:


160

Kanvas öğesi, aygıt veya monitörün piksel oranından bağımsız çalışır.

İPad 3+ üzerinde bu oran 2'dir. Bu, esasen 1000px genişliğindeki kanvasınızın iPad ekranında belirtilen genişliğe uyması için 2000px'i doldurması gerektiği anlamına gelir. Neyse ki bizim için bu, tarayıcı tarafından otomatik olarak yapılır. Öte yandan, görünür alanlarına doğrudan uyacak şekilde yapılmış resimler ve tuval öğelerinde daha az tanım görmenizin nedeni de budur. Kanvasınız yalnızca 1000 piksel doldurmayı bildiğinden ancak 2000 piksele kadar çizim yapması istendiğinden, öğeyi uygun boyutunda görüntülemek için tarayıcının pikseller arasındaki boşlukları akıllıca doldurması gerekir.

Çok okumak öneriyoruz bu yazıyı gelen HTML5Rocks yüksek çözünürlüklü elemanlarını nasıl oluşturulacağını daha detaylı olarak açıklanmaktadır.

tl; dr? İşte kendi projelerimde uygun çözünürlükte bir tuvali çıkarmak için kullandığım bir örnek (yukarıdaki açıklamaya göre):

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);

Bu yardımcı olur umarım!


2
CreateHiDPI () yöntemimin adının biraz kötü olduğunu belirtmenin faydalı olacağını düşündüm. DPI yalnızca baskı için bir terimdir ve monitörler görüntüleri noktaların aksine pikseller kullanarak görüntülediğinden ÜFE daha uygun bir kısaltmadır.
MyNameIsKo

3
Bu oranın aslında sayfanın kullanım ömrü boyunca değişebileceğini unutmayın. Örneğin, bir Chrome penceresini eski bir "standart" res harici monitörden bir macbook'un yerleşik bir retina ekranına sürüklersem, kod farklı bir oran hesaplayacaktır. Bu değeri önbelleğe almayı planlıyorsanız, sadece bir FYI. (merak ediyorsanız, harici oran 1, retina ekranı 2 idi)
Aardvark

1
Bu açıklama için teşekkürler. Peki ya görüntü varlıkları? Her tuval görüntüsünü çift çözünürlükte sağlamamız ve manuel olarak küçültmemiz gerekiyor mu?
Kokodoko

1
Daha fazla bilgi: Windows Phone 8'in IE'si window.devicePixelRatio için her zaman 1'i rapor eder (ve destek piksel çağrısı çalışmaz). 1'de berbat görünüyor, ancak 2 oranı iyi görünüyor. Şimdilik oran hesaplamalarım en az bir 2 döndürüyor (berbat bir geçici çözüm, ancak hedef platformlarım neredeyse hepsi yüksek DPI ekranlara sahip gibi görünen modern telefonlardır). HTC 8X ve Lumia 1020 üzerinde test edildi.
Aardvark

1
@Aardvark: Ayrıca msBackingStorePixelRatio'nun her zaman tanımsız olduğu görülüyor. Burada bununla ilgili yeni bir soru soruldu: stackoverflow.com/questions/22483296/…
TV'den Frank

29

Çözüldü!

Tuval boyutunu nasıl etkilediğini görmek için belirlediğim genişlik ve yükseklik özelliklerini neyin değiştirdiğini görmeye karar verdim javascript- ve etkilemedi. Çözünürlüğü değiştirir.

İstediğim sonucu elde etmek için, aynı zamanda şunların canvas.style.widthfiziksel boyutunu değiştiren niteliği de ayarlamam gerekiyordu 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

1
İdeal sonuçlar için, tuvalin stil niteliklerine hiç dokunmamalı ve boyutu yalnızca tuvalin genişlik ve yükseklik özellikleriyle kontrol etmelisiniz. Bu şekilde, tuval üzerindeki bir pikselin ekrandaki bir piksele eşit olduğundan emin olursunuz.
Philipp

7
Katılmıyorum. Style.width / height niteliklerini değiştirmek, tam olarak bir HiDPI tuvali oluşturduğunuz şekildedir.
MyNameIsKo

2
Cevabınızda, canvas.width'i 1000 ve canvas.style.width'i 500'de yarıya ayarladınız. Bu, yalnızca piksel oranı 2 olan bir cihaz için işe yarıyor. Bunun altındaki herhangi bir şey için, masaüstü monitörünüz gibi, tuval artık gereksiz piksellere çizim. Daha yüksek oranlar için, şimdi bulanık, düşük çözünürlüklü bir varlık / öğe ile başladığınız yere geri döndünüz. Philipp'in kastettiği bir diğer konu da, bağlamınıza çizdiğiniz her şeyin, yarısı değerinde görüntüleniyor olsa bile şimdi iki kat genişliğinize / yüksekliğinize çekilmesi gerektiğidir. Bunun çözümü, tuvalinizin içeriğini ikiye katlamaktır.
MyNameIsKo

3
Var window.devicePixelRatiove çoğu modern tarayıcıda iyi uygulanıyor.
Chen

6

Ana öğenin tüm genişliğini almak için tuval öğesini css aracılığıyla yeniden boyutlandırıyorum. Öğemin genişliğinin ve yüksekliğinin ölçeklenmediğini fark ettim. Olması gereken boyutu ayarlamanın en iyi yolunu arıyordum.

canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;

Bu basit yol, hangi ekranı kullanırsanız kullanın, tuvaliniz mükemmel şekilde ayarlanacaktır.


5

Bu% 100 benim için çözdü:

var canvas = document.getElementById('canvas');
canvas.width = canvas.getBoundingClientRect().width;
canvas.height = canvas.getBoundingClientRect().height;

(Adam Mańkowski'nin çözümüne yakındır).


4

Diğer cevaplarda belirtilmeyen bir ayrıntı fark ettim. Tuval çözünürlüğü tamsayı değerlerine kesilir.

Varsayılan tuval çözünürlüğü boyutları canvas.width: 300ve canvas.height: 150.

Benim ekranımda window.devicePixelRatio: 1.75.

Bu yüzden ayarladığımda canvas.height = 1.75 * 150, değer istenen 262.5seviyeden aşağıya kesilir 262.

Çözüm, belirli bir için CSS mizanpaj boyutlarını seçmektir window.devicePixelRatio, böylece çözünürlüğü ölçeklendirirken kesinti olmaz.

Örneğin, width: 300pxve height: 152pxile çarpıldığında tam sayılar verecek olanı kullanabilirim 1.75.

Düzenleme : Diğer bir çözüm, CSS piksellerinin, tuval piksellerinin ölçeklendirilmesinin kesilmesini önlemek için kesirli olabileceği gerçeğinden yararlanmaktır.

Aşağıda bu stratejiyi kullanan bir demo var.

Düzenleme : İşte OP'nin bu stratejiyi kullanmak için güncellenen keman kısmı: http://jsfiddle.net/65maD/83/ .

main();

// Rerun on window resize.
window.addEventListener('resize', main);


function main() {
  // Prepare canvas with properly scaled dimensions.
  scaleCanvas();

  // Test scaling calculations by rendering some text.
  testRender();
}


function scaleCanvas() {
  const container = document.querySelector('#container');
  const canvas = document.querySelector('#canvas');

  // Get desired dimensions for canvas from container.
  let {width, height} = container.getBoundingClientRect();

  // Get pixel ratio.
  const dpr = window.devicePixelRatio;
  
  // (Optional) Report the dpr.
  document.querySelector('#dpr').innerHTML = dpr.toFixed(4);

  // Size the canvas a bit bigger than desired.
  // Use exaggeration = 0 in real code.
  const exaggeration = 20;
  width = Math.ceil (width * dpr + exaggeration);
  height = Math.ceil (height * dpr + exaggeration);

  // Set the canvas resolution dimensions (integer values).
  canvas.width = width;
  canvas.height = height;

  /*-----------------------------------------------------------
                         - KEY STEP -
   Set the canvas layout dimensions with respect to the canvas
   resolution dimensions. (Not necessarily integer values!)
   -----------------------------------------------------------*/
  canvas.style.width = `${width / dpr}px`;
  canvas.style.height = `${height / dpr}px`;

  // Adjust canvas coordinates to use CSS pixel coordinates.
  const ctx = canvas.getContext('2d');
  ctx.scale(dpr, dpr);
}


function testRender() {
  const canvas = document.querySelector('#canvas');
  const ctx = canvas.getContext('2d');
  
  // fontBaseline is the location of the baseline of the serif font
  // written as a fraction of line-height and calculated from the top
  // of the line downwards. (Measured by trial and error.)
  const fontBaseline = 0.83;
  
  // Start at the top of the box.
  let baseline = 0;

  // 50px font text
  ctx.font = `50px serif`;
  ctx.fillText("Hello World", 0, baseline + fontBaseline * 50);
  baseline += 50;

  // 25px font text
  ctx.font = `25px serif`;
  ctx.fillText("Hello World", 0, baseline + fontBaseline * 25);
  baseline += 25;

  // 12.5px font text
  ctx.font = `12.5px serif`;
  ctx.fillText("Hello World", 0, baseline + fontBaseline * 12.5);
}
/* HTML is red */

#container
{
  background-color: red;
  position: relative;
  /* Setting a border will mess up scaling calculations. */
  
  /* Hide canvas overflow (if any) in real code. */
  /* overflow: hidden; */
}

/* Canvas is green */ 

#canvas
{
  background-color: rgba(0,255,0,.8);
  animation: 2s ease-in-out infinite alternate both comparison;
}

/* animate to compare HTML and Canvas renderings */

@keyframes comparison
{
  33% {opacity:1; transform: translate(0,0);}
  100% {opacity:.7; transform: translate(7.5%,15%);}
}

/* hover to pause */

#canvas:hover, #container:hover > #canvas
{
  animation-play-state: paused;
}

/* click to translate Canvas by (1px, 1px) */

#canvas:active
{
  transform: translate(1px,1px) !important;
  animation: none;
}

/* HTML text */

.text
{
  position: absolute;
  color: white;
}

.text:nth-child(1)
{
  top: 0px;
  font-size: 50px;
  line-height: 50px;
}

.text:nth-child(2)
{
  top: 50px;
  font-size: 25px;
  line-height: 25px;
}

.text:nth-child(3)
{
  top: 75px;
  font-size: 12.5px;
  line-height: 12.5px;
}
<!-- Make the desired dimensions strange to guarantee truncation. -->
<div id="container" style="width: 313.235px; height: 157.122px">
  <!-- Render text in HTML. -->
  <div class="text">Hello World</div>
  <div class="text">Hello World</div>
  <div class="text">Hello World</div>
  
  <!-- Render text in Canvas. -->
  <canvas id="canvas"></canvas>
</div>

<!-- Interaction instructions. -->
<p>Hover to pause the animation.<br>
Click to translate the green box by (1px, 1px).</p>

<!-- Color key. -->
<p><em style="color:red">red</em> = HTML rendered<br>
<em style="color:green">green</em> = Canvas rendered</p>

<!-- Report pixel ratio. -->
<p>Device pixel ratio: <code id="dpr"></code>
<em>(physical pixels per CSS pixel)</em></p>

<!-- Info. -->
<p>Zoom your browser to re-run the scaling calculations.
(<code>Ctrl+</code> or <code>Ctrl-</code>)</p>


3

Canvg ( SVG'den Canvas js kitaplığına) altında MyNameIsKo kodunu biraz uyarladım . Bir süre kafam karıştı ve bunun için biraz zaman harcadım. Umarım bu birine yardımcı olur.

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);

}

2

Reactjs'de çalışanlar için, MyNameIsKo'nun cevabını uyarladım ve harika çalışıyor. İşte kod.

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}/>
        )
    }
}

Bu örnekte, sahne olarak tuvalin genişliğini ve yüksekliğini aktarıyorum.


2

Tuvalinizde şu CSS satırını deneyin: image-rendering: pixelated

Gereğince MDN'yi :

Görüntüyü büyütürken, görüntünün büyük piksellerden oluşması için en yakın komşu algoritması kullanılmalıdır.

Böylece kenar yumuşatmayı tamamen önler.


2

@ MyNameIsKo'nun cevabı hala işe yarasa da, 2020'de biraz modası geçmiş ve geliştirilebilir:

function createHiPPICanvas(w, h) {
    let ratio = window.devicePixelRatio;
    let cv = document.createElement("canvas");
    cv.width = w * ratio;
    cv.height = h * ratio;
    cv.style.width = w + "px";
    cv.style.height = h + "px";
    cv.getContext("2d").scale(ratio, ratio);
    return cv;
}

Genel olarak aşağıdaki iyileştirmeleri yapıyoruz:

  • backingStorePixelRatioReferansları kaldırıyoruz , çünkü bunlar herhangi bir tarayıcıda önemli bir şekilde uygulanmıyor (aslında, yalnızca Safari dışında bir şey döndürüyor undefinedve bu sürüm Safari'de hala mükemmel çalışıyor);
  • Tüm bu oran kodunu şununla değiştiriyoruz: window.devicePixelRatio , fantastik desteği vardır
  • Bu aynı zamanda bir global mülk eksik ilan ettiğimiz anlamına gelir --- yaşasın !!
  • Ayrıca , anlamsız olduğu için || 1geri dönüşü de kaldırabiliriz window.devicePixelRatio: bu özelliği desteklemeyen tüm tarayıcılar.setTransform ya .scaleda ikisini , bu nedenle bu işlev onlarda çalışmaz, geri dönüş ya da değil;
  • Değiştirebiliriz .setTransform göre .scalebir genişlik olarak geçen ve yüksekliği dönüşüm matrisi içinde geçen biraz daha sezgisel.
  • Fonksiyon yeniden adlandırıldı createHiDPICanvasiçin createHiPPICanvas. @MyNameIsKo'nun kendi yanıtlarının yorumlarında belirttiği gibi, DPI (Dots per Inch) baskı terminolojisidir (yazıcılar küçük renkli mürekkep noktalarından görüntüler oluştururken). Benzer olsa da, monitörler görüntüleri piksel kullanarak görüntüler ve bu nedenle PPI (İnç Başına Piksel), kullanım durumumuz için daha iyi bir kısaltmadır.

Bu basitleştirmelerin en büyük yararı, bu cevabın artık TypeScript'te olmadan kullanılabilmesidir // @ts-ignore(TS'nin türleri olmadığı için backingStorePixelRatio).


0

Benim için, yalnızca farklı 'mükemmel piksel' tekniklerinin bir kombinasyonu sonuçların arşivlenmesine yardımcı oldu:

  1. @ MyNameIsKo'nun önerdiği gibi bir piksel oranıyla alın ve ölçekleyin.

    pixelRatio = window.devicePixelRatio / ctx.backingStorePixelRatio

  2. Tuvali yeniden boyutlandırmada ölçekleyin (tuvalin varsayılan genişletme ölçeklemesinden kaçının).

  3. Doğru 'gerçek' piksel çizgi kalınlığını bulmak için pixelRatio ile lineWidth'i çarpın:

    context.lineWidth = kalınlık * pixelRatio;

  4. Çizginin kalınlığının tek mi çift mi olduğunu kontrol edin. pixelRatio'nun yarısını tek kalınlık değerleri için çizgi konumuna ekleyin.

    x = x + pikselOranı / 2;

Tek çizgi pikselin ortasına yerleştirilecektir. Yukarıdaki çizgi onu biraz hareket ettirmek için kullanılır.

function getPixelRatio(context) {
  dpr = window.devicePixelRatio || 1,
    bsr = context.webkitBackingStorePixelRatio ||
    context.mozBackingStorePixelRatio ||
    context.msBackingStorePixelRatio ||
    context.oBackingStorePixelRatio ||
    context.backingStorePixelRatio || 1;

  return dpr / bsr;
}


var canvas = document.getElementById('canvas');
var context = canvas.getContext("2d");
var pixelRatio = getPixelRatio(context);
var initialWidth = canvas.clientWidth * pixelRatio;
var initialHeight = canvas.clientHeight * pixelRatio;


window.addEventListener('resize', function(args) {
  rescale();
  redraw();
}, false);

function rescale() {
  var width = initialWidth * pixelRatio;
  var height = initialHeight * pixelRatio;
  if (width != context.canvas.width)
    context.canvas.width = width;
  if (height != context.canvas.height)
    context.canvas.height = height;

  context.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
}

function pixelPerfectLine(x) {

  context.save();
  context.beginPath();
  thickness = 1;
  // Multiple your stroke thickness  by a pixel ratio!
  context.lineWidth = thickness * pixelRatio;

  context.strokeStyle = "Black";
  context.moveTo(getSharpPixel(thickness, x), getSharpPixel(thickness, 0));
  context.lineTo(getSharpPixel(thickness, x), getSharpPixel(thickness, 200));
  context.stroke();
  context.restore();
}

function pixelPerfectRectangle(x, y, w, h, thickness, useDash) {
  context.save();
  // Pixel perfect rectange:
  context.beginPath();

  // Multiple your stroke thickness by a pixel ratio!
  context.lineWidth = thickness * pixelRatio;
  context.strokeStyle = "Red";
  if (useDash) {
    context.setLineDash([4]);
  }
  // use sharp x,y and integer w,h!
  context.strokeRect(
    getSharpPixel(thickness, x),
    getSharpPixel(thickness, y),
    Math.floor(w),
    Math.floor(h));
  context.restore();
}

function redraw() {
  context.clearRect(0, 0, canvas.width, canvas.height);
  pixelPerfectLine(50);
  pixelPerfectLine(120);
  pixelPerfectLine(122);
  pixelPerfectLine(130);
  pixelPerfectLine(132);
  pixelPerfectRectangle();
  pixelPerfectRectangle(10, 11, 200.3, 443.2, 1, false);
  pixelPerfectRectangle(41, 42, 150.3, 443.2, 1, true);
  pixelPerfectRectangle(102, 100, 150.3, 243.2, 2, true);
}

function getSharpPixel(thickness, pos) {

  if (thickness % 2 == 0) {
    return pos;
  }
  return pos + pixelRatio / 2;

}

rescale();
redraw();
canvas {
  image-rendering: -moz-crisp-edges;
  image-rendering: -webkit-crisp-edges;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
  width: 100vh;
  height: 100vh;
}
<canvas id="canvas"></canvas>

Yeniden boyutlandırma olayı, alıntılamada tetiklenmez, böylece dosyayı github'da deneyebilirsiniz


0

Benim için sadece görüntü değil, metin de kötü kalitede. Retina / retina olmayan ekranlar için en basit çapraz tarayıcı çalışma çözümü, görüntüyü amaçlanandan iki kat daha büyük oluşturmak ve bu adamın önerdiği gibi tuval içeriğini ölçeklendirmekti: https://stackoverflow.com/a/53921030/4837965

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.