天道酬勤,学无止境

如何修复HTML5画布中的模糊文本?(How do I fix blurry text in my HTML5 canvas?)

问题

我总的n00b HTML5和我有工作canvas渲染形状,颜色和文字。 在我的应用程序中,我有一个视图适配器,可以动态创建画布,并用内容填充它。 效果非常好,除了我的文本非常模糊/模糊/拉伸。 我还看到了许多其他文章,说明为什么在CSS定义宽度高度会导致此问题,但我在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);
 <div id="layout-content"></div>

我看到的结果(在Safari中)比Fiddle中显示的要歪斜得多:

在Safari中呈现输出

小提琴

在JSFiddle上呈现输出

我做错了什么? 每个文本元素都需要一个单独的画布吗? 是字体吗? 我需要首先在HTML5布局中定义画布吗? 有错字吗? 我搞不清楚了。

回答1

canvas元素的运行独立于设备或监视器的像素比率。

在iPad 3+上,该比例为2。这实际上意味着您现在需要将1000px宽度的画布填充2000px,以与其在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);

希望这可以帮助!

回答2

解决了!

我决定看看是什么改变了我在javascript设置的widthheight属性,以了解这如何影响画布的大小-并没有。 它改变了分辨率。

为了获得想要的结果,我还必须设置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
回答3

我通过CSS调整画布元素的大小,以获取父元素的整个宽度。 我注意到元素的宽度和高度没有缩放。 我一直在寻找设置尺寸的最佳方法。

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

无论您使用哪种屏幕,都可以通过这种简单的方式完美设置画布。

回答4

这100%为我解决了这个问题:

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

(它接近AdamMańkowski的解决方案)。

回答5

我注意到其他答案中未提及的细节。 画布分辨率会截断为整数值。

默认的画布分辨率尺寸为canvas.width: 300canvas.height: 150

在我的屏幕上, window.devicePixelRatio: 1.75

因此,当我设置canvas.height = 1.75 * 150该值将从所需的262.5截断为262

一种解决方案是为给定的window.devicePixelRatio选择CSS布局尺寸,以便在缩放分辨率时不会发生截断。

例如,我可以使用width: 300pxheight: 152px乘以1.75会产生整数。

编辑:另一个解决方案是利用CSS像素可以分数的事实来抵消缩放画布像素的截断。

以下是使用此策略的演示。

编辑:这是OP的小提琴,已更新为使用此策略: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>
回答6

我在canvg(将SVG转换为Canvas js库)下略微修改了MyNameIsKo代码。 我有些困惑,花了一些时间。 希望这对某人有帮助。

的HTML

<div id="chart"><canvas></canvas><svg>Your SVG here</svg></div>

Java脚本

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

}
回答7

在您的画布上尝试以下CSS代码: image-rendering: pixelated

根据MDN:

在放大图像时,必须使用最近邻居算法,以便图像看起来由大像素组成。

因此,它完全防止了抗锯齿。

回答8

尽管@MyNameIsKo的答案仍然有效,但到2020年它已经有些过时了,可以改进:

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

总的来说,我们进行了以下改进:

  • 我们删除了backingStorePixelRatio引用,因为这些引用实际上并没有以任何重要方式在任何浏览器中实现(实际上,只有Safari返回的是undefined以外的东西,并且该版本在Safari中仍然可以正常使用);
  • 我们将所有比率代码替换为window.devicePixelRatio ,它具有出色的支持
  • 这也意味着我们要少申报一个全球财产---万岁!
  • 我们也可以删除|| 1window.devicePixelRatio上有|| 1后备,因为这毫无意义:所有不支持此属性的浏览器都不支持.setTransform.scale ,因此,无论.setTransform .scale ,此功能都将对其不起作用;
  • 我们可以将.setTransform替换为.scale ,因为传递宽度和高度比传递变换矩阵更直观。
  • 该函数已从createHiDPICanvas重命名为createHiPPICanvas 。 正如@MyNameIsKo自己在答案中提到的那样,DPI(每英寸点数)是打印术语(因为打印机是用彩色墨水的细小点组成图像的)。 尽管类似,但监视器使用像素显示图像,因此PPI(每英寸像素)是我们用例的更好的缩写。

这些简化的一大好处是,现在可以在TypeScript中使用此答案,而无需// @ts-ignore (因为TS没有用于backingStorePixelRatio类型)。

回答9

对于那些在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}/>
        )
    }
}

在此示例中,我传入了画布的宽度和高度作为道具。

回答10

对我而言,只有不同的“像素完美”技术的组合才有助于存档结果:

  1. 按照@MyNameIsKo建议的像素比例进行获取和缩放。

    pixelRatio = window.devicePixelRatio / ctx.backingStorePixelRatio

  2. 在调整大小时缩放画布(避免使用画布默认的拉伸比例)。

  3. 将lineWidth与pixelRatio乘以找到正确的“真实”像素线粗度:

    context.lineWidth =厚度* pixelRatio;

  4. 检查线的粗细是否为奇数或偶数。 将奇数厚度值的一半pixelRatio添加到行位置。

    x = x + pixelRatio / 2;

奇数行将放置在像素的中间。 上面的线用于将其稍微移动一点。

 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>

调整大小事件不会在已剪裁中触发,因此您可以在github上尝试该文件

回答11

对我来说,这不仅是图像,而且文字质量很差。 适用于视网膜/非视网膜显示器的最简单的跨浏览器工作解决方案是渲染图像两倍于预期大小,并按此人的建议缩放画布上下文:https://stackoverflow.com/a/53921030/4837965

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 使用CSS转换后的文本模糊:scale(); 在Chrome中(Blurry text after using CSS transform: scale(); in Chrome)
    问题 似乎最近对Google Chrome浏览器进行了更新,该更新在执行以下transform: scale()后导致文本模糊transform: scale() 。 具体来说,我正在这样做: @-webkit-keyframes bounceIn { 0% { opacity: 0; -webkit-transform: scale(.3); } 50% { opacity: 1; -webkit-transform: scale(1.05); } 70% { -webkit-transform: scale(.9); } 100% { -webkit-transform: scale(1); } } 如果您在Chrome中访问http://rourkery.com,则应该在主要文本区域中看到问题。 它以前没有这样做,并且似乎也没有影响其他Webkit浏览器(例如Safari)。 还有其他一些关于人们在使用3d变换时遇到类似问题的帖子,但找不到像这样的关于2d变换的任何信息。 任何想法将不胜感激,谢谢! 回答1 我多次遇到此问题,似乎有2种解决方法(如下所示)。 您可以使用这两个属性之一来修复渲染,也可以同时使用这两个属性。 隐藏的背面可见性解决了该问题,因为它将动画简化为仅位于对象的正面,而默认状态为正面和背面。 backface-visibility: hidden
  • How do I fix blurry text in my HTML5 canvas?
    I am a total n00b with HTML5 and am working with the canvas to render shapes, colors, and text. In my app, I have a view adapter that creates a canvas dynamically, and fills it with content. This works really nicely, except that my text is rendered very fuzzy/blurry/stretched. I have seen a lot of other posts on why defining the width and height in CSS will cause this issue, but I define it all in javascript. The relevant code (view Fiddle): var width = 500;//FIXME:size.w; var height = 500;//FIXME:size.h; var canvas = document.createElement("canvas"); //canvas.className="singleUserCanvas"
  • WPF模糊字体问题-解决方案(WPF Blurry fonts issue- Solutions)
    问题 在以下链接上描述并演示了该问题: Paul Stovell WPF:模糊文本渲染 www.gamedev.net论坛 Microsoft Connect:WPF文本渲染器以小字体产生严重模糊的文本 说明:WPF中的文本清晰度。 此链接具有字体比较。 我想收集这个问题的所有可能的解决方案。 Microsoft Expression Blend使用WPF,但字体看起来可读。 如Microsoft Expression Blend中的深色背景增加字体大小并更改字体(Calibri ...)[链接] 嵌入Windows表单[链接] 使用GDI +和/或Windows Forms TextRenderer类将文本呈现为位图,然后将该位图呈现为WPF控件。 [关联] 还有其他解决方案吗? 这将在VS2010(和WPF4)测试版2中修复 它看起来像已经解决了! 斯科特·汉塞尔曼(Scott Hanselman)的ComputerZen.com:WPF和文本模糊,现在完全清晰 回答1 技术背景 在Windowsclient.net上有一篇有关WPF文本呈现的深入文章,来自WPF文本程序管理器之一:WPF中的文本清晰度。 问题归结为WPF,需要线性缩放的字体渲染器来平滑动画。 另一方面,Pure ClearType在字体方面具有相当大的自由度,可将垂直词干推入下一个像素。 如果人们比较经典的
  • HTML5中的画布宽度和高度(Canvas width and height in HTML5)
    问题 是否可以固定HTML5 canvas元素的宽度和高度? 通常的方法如下: <canvas id="canvas" width="300" height="300"></canvas> 回答1 canvas DOM元素具有.height和.width属性,它们与height="…"和width="…"属性相对应。 在JavaScript代码中将它们设置为数值,以调整画布的大小。 例如: var canvas = document.getElementsByTagName('canvas')[0]; canvas.width = 800; canvas.height = 600; 请注意,这将清除画布,尽管您应遵循ctx.clearRect( 0, 0, ctx.canvas.width, ctx.canvas.height); 来处理那些没有完全清除画布的浏览器。 尺寸更改后,您需要重绘要显示的所有内容。 进一步注意的是,高度和宽度是用于绘制逻辑帆布尺寸和来自不同style.height和style.width CSS属性。 如果您未设置CSS属性,则画布的固有大小将用作其显示大小; 如果您确实设置了CSS属性,并且它们与画布尺寸不同,则将在浏览器中缩放内容。 例如: // Make a canvas that has a blurry pixelated zoom-in //
  • 如何找到HTML画布上文本的高度?(How can you find the height of text on an HTML canvas?)
    问题 规范中有一个context.measureText(text)函数,该函数将告诉您打印该文本需要多少宽度,但是我找不到找到高度的方法。 我知道它是基于字体的,但是我不知道将字体字符串转换为文本高度。 回答1 更新-作为此工作的示例,我在Carota编辑器中使用了此技术。 继ellisbben的回答之后,这是一个增强版本,可从基线获得上升和下降,即与Win32的GetTextMetric API返回的tmAscent和tmDescent相同。 如果您想用不同字体/大小的跨度进行文字包装的文本,则需要这样做。 上面的图像是在Safari中的画布上生成的,红色是指示画布绘制文本的最上面一行,绿色是基线,蓝色是底部(所以红色到蓝色是完整高度)。 使用jQuery简洁: var getTextHeight = function(font) { var text = $('<span>Hg</span>').css({ fontFamily: font }); var block = $('<div style="display: inline-block; width: 1px; height: 0px;"></div>'); var div = $('<div></div>'); div.append(text, block); var body = $('body'); body
  • HTML5画布和抗锯齿(HTML5 Canvas and Anti-aliasing)
    问题 如何在画布上打开抗锯齿功能。 以下代码无法画出一条流畅的线: var context = mainCanv.getContext("2d"); if (context) { context.moveTo(0,0); context.lineTo(100,75); context.strokeStyle = "#df4b26"; context.lineWidth = 3; context.stroke(); } 回答1 抗锯齿功能无法打开或关闭,并且由浏览器控制。 我可以关闭HTML <canvas>元素上的抗锯齿功能吗? 回答2 您可以按半像素距离平移画布。 ctx.translate(0.5, 0.5); 最初,画布在物理像素之间的定位点。 回答3 我不需要打开抗锯齿功能,因为默认情况下该功能处于打开状态,但是我需要将其关闭。 如果可以将其关闭,则也可以将其打开。 ctx.imageSmoothingEnabled = true; 当我在画布rpg上工作时,通常会关闭它,因此在放大图像时看起来不会模糊。 回答4 现在到了2018年,我们终于有了便宜的方法来做一些事情... 实际上,由于2d上下文API现在具有filter属性,并且此filter属性可以接受SVGFilters,因此我们可以构建一个SVGFilter,该SVGFilter将仅保留图形中的完全不透明像素
  • HTML5 canvas drawImage:如何应用抗锯齿(Html5 canvas drawImage: how to apply antialiasing)
    问题 请看下面的例子: http://jsfiddle.net/MLGr4/47/ var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); img = new Image(); img.onload = function(){ canvas.width = 400; canvas.height = 150; ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, 400, 150); } img.src = "http://openwalls.com/image/1734/colored_lines_on_blue_background_1920x1200.jpg"; 如您所见,尽管据说drawImage自动应用了抗锯齿功能,但该图像并未进行抗锯齿处理。 我尝试了许多不同的方法,但是似乎没有用。 您能告诉我如何获得抗锯齿图像吗? 谢谢。 回答1 原因 当您要从大尺寸变为小尺寸时,有些图像很难进行下采样和插值,例如带有曲线的图像。 由于性能原因,浏览器似乎通常对画布元素使用双线性(2x2采样)插值,而不是双三次(4x4采样)插值。 如果步幅太大,则根本没有足够的像素可采样,结果将在像素中反映出来。 从信号/ DSP的角度来看
  • 如何使HTML文本框为空时显示提示?(How do I make an HTML text box show a hint when empty?)
    问题 我希望网页上的搜索框以灰色斜体显示单词“搜索”。 当该框获得焦点时,它应该看起来像一个空的文本框。 如果其中已经有文本,则应正常显示文本(黑色,非斜体)。 这将有助于我通过除去标签来避免混乱。 顺便说一句,这是页面上的Ajax搜索,因此没有按钮。 回答1 如果您很高兴只对较新的浏览器拥有此功能,那么另一个选择是使用HTML 5的占位符属性提供的支持: <input name="email" placeholder="Email Address"> 在没有任何样式的情况下,Chrome中的外观如下: 您可以在此处以及使用CSS的HTML5占位符样式中进行演示。 确保检查此功能的浏览器兼容性。 3.7中添加了对Firefox的支持。 铬很好。 Internet Explorer仅在10中添加了支持。如果定位的浏览器不支持输入占位符,则可以使用名为jQuery HTML5 Placeholder的jQuery插件,然后只需添加以下JavaScript代码即可启用它。 $('input[placeholder], textarea[placeholder]').placeholder(); 回答2 这就是所谓的文本框水印,它是通过JavaScript完成的。 http://naspinski.net/post/Text-Input-Watermarks-using
  • 如何使用JavaScript将焦点放在HTML表单中的元素上?(How can I set focus on an element in an HTML form using JavaScript?)
    问题 我有一个带有文本框的Web表单。 默认情况下,如何将焦点设置到文本框? 像这样的东西: <body onload='setFocusToTextBox()'> 所以有人可以帮我吗? 我不知道如何使用JavaScript将焦点设置到文本框。 <script> function setFocusToTextBox(){ //What to do here } </script> 回答1 做这个。 如果您的元素是这样的。 <input type="text" id="mytext"/> 您的脚本将是 <script> function setFocusToTextBox(){ document.getElementById("mytext").focus(); } </script> 回答2 对于它的价值,您可以在HTML5兼容的浏览器上使用autofocus属性。 从版本10开始甚至可以在IE上使用。 <input name="myinput" value="whatever" autofocus /> 回答3 通常,当我们专注于文本框时,我们还应该滚动到视图中 function setFocusToTextBox(){ var textbox = document.getElementById("yourtextbox"); textbox.focus(); textbox
  • How to draw a blurry circle on HTML5 canvas?
    I'm able to draw a simple circle on HTML5 canvas, but I'd like to add some blur around it. What I found was this website which explains the shadowBlur property which can come in handy here. However, I cannot manage to make the circle itself blurry. What the shadowBlur property basically does is painting some blur effect after the regular circle has been drawn. What I've tried so far I've put on jsFiddle. As can be seen, it's a solid filled circle with some blur effect around it - the two parts do not blend into each other at all. What I actually would like to achieve is that the circle itself
  • HTML5画布调整大小(缩小)图像的质量?(HTML5 Canvas Resize (Downscale) Image High Quality?)
    问题 我使用html5 canvas元素在浏览器中调整图像大小。 事实证明,质量很低。 我发现了这一点:在缩放<canvas>时禁用插值,但它无助于提高质量。 下面是我的css和js代码,以及用Photoshop调用并在canvas API中缩放的图像。 在浏览器中缩放图像时,我该怎么做才能获得最佳质量? 注意:我想将大图像缩小为小图像,修改画布中的颜色并将结果从画布发送到服务器。 CSS: canvas, img { image-rendering: optimizeQuality; image-rendering: -moz-crisp-edges; image-rendering: -webkit-optimize-contrast; image-rendering: optimize-contrast; -ms-interpolation-mode: nearest-neighbor; } JS: var $img = $('<img>'); var $originalCanvas = $('<canvas>'); $img.load(function() { var originalContext = $originalCanvas[0].getContext('2d'); originalContext.imageSmoothingEnabled = false
  • 如何在html5画布中绘制椭圆形?(How to draw an oval in html5 canvas?)
    问题 似乎没有绘制椭圆形形状的本机功能。 我也不是在寻找鸡蛋的形状。 是否可以绘制具有2个贝塞尔曲线的椭圆形? 有人遇到过吗? 我的目的是画一些眼睛,实际上我只是使用弧线。 提前致谢。 解决方案 因此,scale()更改所有下一个形状的缩放比例。 Save()之前保存设置,还原用于还原设置以绘制新形状而无需缩放。 感谢Jani ctx.save(); ctx.scale(0.75, 1); ctx.beginPath(); ctx.arc(20, 21, 10, 0, Math.PI*2, false); ctx.stroke(); ctx.closePath(); ctx.restore(); 回答1 更新: 缩放方法可能会影响笔触宽度的外观正确的缩放方法可以保持笔触宽度完整画布具有Chrome现在支持的椭圆方法向JSBin添加了更新的测试 JSBin测试示例(已更新以测试其他人的答案以进行比较) 贝塞尔曲线-基于包含矩形和宽度/高度的左上方绘制带中心的贝塞尔曲线-根据中心和宽度/高度绘制圆弧和缩放-基于绘制圆和缩放进行绘制见德文·卡拉(Deven Kalra)的答案二次曲线-用二次曲线绘制测试似乎不完全相同,可能是实现看到oyophant的答案画布椭圆-使用W3C标准ellipse()方法测试似乎不完全相同,可能是实现见洛克塔尔的答案 原来的: 如果您想要一个对称的椭圆形
  • 如何获得在画布元素上单击鼠标的坐标?(How do I get the coordinates of a mouse click on a canvas element?)
    问题 将click事件处理程序添加到canvas元素(将返回click的x和y坐标(相对于canvas元素))的最简单方法是什么? 不需要旧版浏览器兼容性,Safari,Opera和Firefox都可以。 回答1 编辑2018:这个答案很老了,它使用检查不再需要的旧浏览器,因为clientX和clientY属性在所有当前浏览器中都有效。 您可能想查看Patriques Answer,以获得更简单,最新的解决方案。 原始答案: 正如我当时发现的一篇文章中所述,但不再存在: var x; var y; if (e.pageX || e.pageY) { x = e.pageX; y = e.pageY; } else { x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; } x -= gCanvasElement.offsetLeft; y -= gCanvasElement.offsetTop; 对我来说工作得很好。 回答2 如果您喜欢简单性,但仍然想要跨浏览器功能,那么我发现此解决方案最适合我。 这是
  • 如何修复getImageData()错误画布已被跨域数据污染?(How to fix getImageData() error The canvas has been tainted by cross-origin data?)
    问题 我的代码在localhost上运行良好,但在站点上不运行。 我从控制台收到此行.getImageData(x,y,1,1).data : Uncaught SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data. 我的代码的一部分: jQuery.Event.prototype.rgb=function(){ var x = this.offsetX || (this.pageX - $(this.target).offset().left),y = this.offsetY || (this.pageY - $(this.target).offset().top); if (this.target.nodeName!=="CANVAS")return null; return this.target.getContext('2d').getImageData(x,y,1,1).data; } 注意:我的图片网址(src)来自子域网址 回答1 正如其他人所说,您是通过从跨起源域加载来“污染”画布的。 https://developer.mozilla.org/zh-CN/docs
  • 如何使用canvas.toDataURL()将画布另存为图像?(How To Save Canvas As An Image With canvas.toDataURL()?)
    问题 我目前正在构建HTML5 Web应用程序/ Phonegap本机应用程序,但似乎无法弄清楚如何使用canvas.toDataURL()将画布另存为图像。 有人可以帮我吗? 这是代码,这是怎么回事? //我的画布被命名为“ canvasSignature” JavaScript: function putImage() { var canvas1 = document.getElementById("canvasSignature"); if (canvas1.getContext) { var ctx = canvas1.getContext("2d"); var myImage = canvas1.toDataURL("image/png"); } var imageElement = document.getElementById("MyPix"); imageElement.src = myImage; } HTML5: <div id="createPNGButton"> <button onclick="putImage()">Save as Image</button> </div> 回答1 这是一些代码。 没有任何错误。 var image = canvas.toDataURL("image/png").replace("image/png", "image
  • 如何使用WebBrowser控件上的DrawToBitmap修复不透明度错误?(How to fix a opacity bug with DrawToBitmap on WebBrowser Control?)
    问题 根据以下链接和我的控制台应用程序,方法DrawToBitmap不尊重不透明度。 证明链接:http://social.msdn.microsoft.com/Forums/vstudio/en-US/e9704309-0c52-442d-80e0-2f8393dcd313/webbrowser-opacity-problem- 我的HTML代码:http://fiddle.jshell.net/L37TC/ <div id="fader" style="background-color: #ff0000">ffff</div> <div style="background-color: blue; opacity:0;filter:alpha(opacity=0);">HIDDEN TEXT!</div> SomeText 我的C#控制台代码: var bmp = new Bitmap(640,480, PixelFormat::Format32bppArgb) var web = (System.Windows.Forms.Control)sender; web.DrawToBitmap(bmp, Rectangle(0, 0, 640,480)); 所以我在寻找内置的解决方案替代.NET(无CEF,Awesomium,或任何扩展请)只是一个内置的
  • 如何在IE8和9中支持占位符属性(How to support placeholder attribute in IE8 and 9)
    问题 我有一个小问题,IE 8-9不支持输入框的placeholder属性。 在我的项目(ASP Net)中获得这种支持的最佳方法是什么。 我正在使用jQuery。 我需要使用其他一些外部工具吗? http://www.hagenburger.net/BLOG/HTML5-Input-Placeholder-Fix-With-jQuery.html是一个好的解决方案吗? 回答1 您可以使用以下jQuery插件:https://github.com/mathiasbynens/jquery-placeholder 但是您的链接似乎也是一个很好的解决方案。 回答2 您可以使用以下任何一种polyfill: https://github.com/jamesallardice/Placeholders.js(不支持密码字段) https://github.com/chemerisuk/better-placeholder-polyfill 这些脚本将在不支持placeholder属性的浏览器中添加对它们的支持,并且它们不需要jQuery! 回答3 $ .Browser.msie不再在最新的JQuery上...您必须使用$ .support 如下所示: <script> (function ($) { $.support.placeholder = ('placeholder' in
  • 创建模糊的叠加视图(Creating a blurring overlay view)
    问题 在新iOS的“音乐”应用中,我们可以在模糊其视图的后面看到专辑封面。 这样的事情怎么能实现呢? 我已经阅读了文档,但是没有找到任何东西。 回答1 您可以使用UIVisualEffectView达到此效果。 这是一个本机API,已针对性能和更长的电池寿命进行了微调,并且易于实现。 迅速: //only apply the blur if the user hasn't disabled transparency effects if !UIAccessibility.isReduceTransparencyEnabled { view.backgroundColor = .clear let blurEffect = UIBlurEffect(style: .dark) let blurEffectView = UIVisualEffectView(effect: blurEffect) //always fill the view blurEffectView.frame = self.view.bounds blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight] view.addSubview(blurEffectView) //if you have more UIViews, use an
  • 如何强制WebKit重绘/重绘以传播样式更改?(How can I force WebKit to redraw/repaint to propagate style changes?)
    问题 我有一些琐碎的JavaScript可以实现样式更改: sel = document.getElementById('my_id'); sel.className = sel.className.replace(/item-[1-9]-selected/,'item-1-selected'); return false; 在最新版本的FF,Opera和IE上可以正常使用,但在最新版本的Chrome和Safari上无法使用。 它影响了两个后代,它们恰好是兄弟姐妹。 第一个同级更新,但第二个不更新。 第二个元素的子元素也具有焦点,并包含<a>标记,该标记在onclick属性中包含上述代码。 如果我微调(例如取消选中和选中)任何元素的任何属性,则在Chrome“开发人员工具”窗口中,第二个兄弟姐妹将更新为正确的样式。 是否有一种解决方法可以轻松地以编程方式“推动” WebKit做正确的事情? 回答1 我发现了一些复杂的建议,许多简单的建议都行不通,但是Vasil Dinkov对其中的一个建议提供了一种简单的解决方案,可以强制重新绘制/重新绘制效果很好: sel.style.display='none'; sel.offsetHeight; // no need to store this anywhere, the reference is enough sel.style
  • 画布中鼠标的实际位置[重复](Real mouse position in canvas [duplicate])
    问题 这个问题已经在这里有了答案: 如何获得在画布元素上单击鼠标的坐标? (22个答案) 1年前关闭。 我正在尝试用鼠标在HTML5画布上绘制,但是似乎正常工作的唯一方法是,如果出于某种原因,如果我更改了画布的位置,那么画布是否位于0,0(左上角)的位置它不会像应该的那样绘制。 这是我的代码。 function createImageOnCanvas(imageId){ document.getElementById("imgCanvas").style.display = "block"; document.getElementById("images").style.overflowY= "hidden"; var canvas = document.getElementById("imgCanvas"); var context = canvas.getContext("2d"); var img = new Image(300,300); img.src = document.getElementById(imageId).src; context.drawImage(img, (0),(0)); } function draw(e){ var canvas = document.getElementById("imgCanvas"); var context =