- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我在将 SVG 渲染到 Canvas 上时遇到问题。在视网膜显示 Canvas 呈现为 base64 url 并设置为 SRC 到是模糊的。
我尝试了以下列表中描述的各种方法,但没有成功:
最佳答案
Retina显示屏
视网膜和超高分辨率显示器的像素尺寸小于人眼的平均分辨率。渲染一条线最终看起来像一条更轻的线。为了解决涉及检测高分辨率显示的页面的问题,会将默认 CSS 像素大小更改为 2。
DOM 知道这一点并调整其渲染以进行补偿。但 Canvas 不知道,它的渲染只是按比例放大。 Canvas 的默认显示渲染类型是双线性插值。这可以平滑从一个像素到下一个像素的过渡,这对于照片来说非常有用,但对于线条、文本、SVG 等来说就不那么好了。
一些解决方案
image-rendering: pixelated;
来完成。虽然这不会创建在 DOM 上呈现的 SVG 的质量,但它会减少一些用户体验的模糊外观。 ctx.imageSmoothingEnabled = false;
devicePixelRatio
返回 CSS 像素的大小与实际屏幕物理像素大小的比较。 Retina 和高分辨率设备的值通常为 2。然后您可以使用它来设置 Canvas 分辨率以匹配物理像素分辨率。devicePixelRatio
,并且devicePixelRatio
受页面缩放设置的影响。devicePixelRatio
并假设很少有人放大 200%。 canvas.style.width
和
canvas.style.height
已经正确设置。
if(devicePixelRatio >= 2){
canvas.width *= 2;
canvas.height *= 2;
}
function setCanvasForRetina(canvas){
canvas.width *= 2;
canvas.height *= 2;
canvas.setTransform(2,0,0,2,0,0);
}
Note I do not increase the pixel size by the value of "devicePixelRatio" This is because retina devices will only have a resolution of 2 times, if the aspect ratio is greater than 2 it is because the client has zoomed in. To honor the expected behaviour of the canvas I do not adjust for zoom setting if I can. Though that is not a rule just a suggestion.
window.screen.width
和
window.screen.height
以确定绝对物理像素分辨率并将其与已知的视网膜显示分辨率相匹配。您还可以查询 userAgent 以确定设备类型和品牌。
rWidth.textContent = screen.width
rHeight.textContent = screen.height
aWidth.textContent = screen.availWidth
aHeight.textContent = screen.availHeight
pWidth.textContent = innerWidth
pHeight.textContent = innerHeight
dWidth.textContent = document.body.clientWidth
dHeight.textContent = document.body.clientHeight
//doWidth.textContent = document.body.offsetWidth
//doHeight.textContent = document.body.offsetHeight
//sWidth.textContent = document.body.scrollWidth
//sHeight.textContent = document.body.scrollHeight
pAspect.textContent = devicePixelRatio
userA.textContent = navigator.userAgent
function isRetina(){
// source https://en.wikipedia.org/wiki/Retina_Display#Models
var knownRetinaResolutions = [[272,340], [312,390], [960,640], [1136,640 ], [1334,750 ], [1920,1080], [2048,1536], [2732,2048], [2304,1440], [2560,1600], [2880,1800], [4096,2304], [5120,2880]];
var knownPhones = [[960,640], [1136,640 ], [1334,750 ], [1920,1080]];
var knownPads = [[2048,1536], [2732,2048]];
var knownBooks = [[2304,1440], [2560,1600], [2880,1800], [4096,2304], [5120,2880]];
var hasRetinaRes = knownRetinaResolutions.some(known => known[0] === screen.width && known[1] === screen.height);
var isACrapple = /(iPhone|iPad|iPod|Mac OS X|MacPPC|MacIntel|Mac_PowerPC|Macintosh)/.test(navigator.userAgent);
var hasPhoneRes = knownPhones.some(known => known[0] === screen.width && known[1] === screen.height);
var isPhone = /iPhone/.test(navigator.userAgent);
var hasPadRes = knownPads.some(known => known[0] === screen.width && known[1] === screen.height);
var isPad = /iPad/.test(navigator.userAgent);
var hasBookRes = knownBooks.some(known => known[0] === screen.width && known[1] === screen.height);
var isBook = /Mac OS X|MacPPC|MacIntel|Mac_PowerPC|Macintosh/.test(navigator.userAgent);
var isAgentMatchingRes = (isBook && hasBookRes && !isPad && !isPhone) ||
(isPad && hasPadRes && !isBook && !isPhone) ||
(isPhone && hasPhoneRes && !isBook && !isPad)
return devicePixelRatio >= 2 &&
isACrapple &&
hasRetinaRes &&
isAgentMatchingRes;
}
guess.textContent = isRetina() ? "Yes" : "No";
div, h1, span {
font-family : arial;
}
span {
font-weight : bold
}
<div class="r-display" id="info">
<h1>System info</h1>
<div>Device resolution :
<span id = "rWidth"></span> by <span id = "rHeight"></span> pixels
</div>
<div>Availabe resolution :
<span id = "aWidth"></span> by <span id = "aHeight"></span> pixels
</div>
<div>Page resolution :
<span id = "pWidth"></span> by <span id = "pHeight"> </span> CSS pixels
</div>
<div>Document client res :
<span id = "dWidth"></span> by <span id = "dHeight"> </span> CSS pixels
</div>
<div>Pixel aspect :
<span id = "pAspect"></span>
</div>
<div>User agent :
<span id="userA"></span>
</div>
<h3>Best guess is retina "<span id = "guess"></span>!"</h3>
</div>
function isRetina() {
// source https://en.wikipedia.org/wiki/Retina_Display#Models
var knownRetinaResolutions = [[272, 340], [312, 390], [960, 640], [1136, 640], [1334, 750], [1920, 1080], [2048, 1536], [2732, 2048], [2304, 1440], [2560, 1600], [2880, 1800], [4096, 2304], [5120, 2880]];
var knownPhones = [[960, 640], [1136, 640], [1334, 750], [1920, 1080]];
var knownPads = [[2048, 1536], [2732, 2048]];
var knownBooks = [[2304, 1440], [2560, 1600], [2880, 1800], [4096, 2304], [5120, 2880]];
var hasRetinaRes = knownRetinaResolutions.some(known => known[0] === screen.width && known[1] === screen.height);
var isACrapple = /(iPhone|iPad|iPod|Mac OS X|MacPPC|MacIntel|Mac_PowerPC|Macintosh)/.test(navigator.userAgent);
var hasPhoneRes = knownPhones.some(known => known[0] === screen.width && known[1] === screen.height);
var isPhone = /iPhone/.test(navigator.userAgent);
var hasPadRes = knownPads.some(known => known[0] === screen.width && known[1] === screen.height);
var isPad = /iPad/.test(navigator.userAgent);
var hasBookRes = knownBooks.some(known => known[0] === screen.width && known[1] === screen.height);
var isBook = /Mac OS X|MacPPC|MacIntel|Mac_PowerPC|Macintosh/.test(navigator.userAgent);
var isAgentMatchingRes = (isBook && hasBookRes && !isPad && !isPhone) ||
(isPad && hasPadRes && !isBook && !isPhone) ||
(isPhone && hasPhoneRes && !isBook && !isPad);
return devicePixelRatio >= 2 && isACrapple && hasRetinaRes && isAgentMatchingRes;
}
function svgToImage(svg){
function svgAsImg() {
var canvas, ctx;
canvas = document.createElement("canvas");
ctx = canvas.getContext("2d");
var width = this.width;
var height = this.height;
var scale = 1;
if(isRetina()){
width *= 2;
height *= 2;
scale = 2;
}
canvas.width = width;
canvas.height = height;
ctx.setTransform(scale, 0, 0, scale, 0, 0);
ctx.imageSmoothingEnabled = false; // SVG rendering is better with smoothing off
ctx.drawImage(this,0,0);
DOMURL.revokeObjectURL(url);
try{
var image = new Image();
image.src = canvas.toDataURL();
imageContainer.appendChild(image);
image.width = this.width;
image.height = this.height;
}catch(e){ // in case of CORS error fallback to canvas
canvas.style.width = this.width + "px"; // in CSS pixels not physical pixels
canvas.style.height = this.height + "px";
imageContainer.appendChild(canvas); // just use the canvas as it is an image as well
}
};
var url;
var img = new Image();
var DOMURL = window.URL || window.webkitURL || window;
img.src = url = DOMURL.createObjectURL(new Blob([svg], {type: 'image/svg+xml'}));
img.onload = svgAsImg;
}
svgToImage(svgContainer.innerHTML);
<div id="svgContainer"><svg width="31" height="40" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 43 55" fill="#736b9e"><path d="m 40.713968,30.966202 c 0.0028,0.05559 -0.01078,0.114956 -0.044,0.178882 -1.545645,2.974287 -2.853499,5.591663 -4.339695,7.673668 -0.788573,1.104704 -2.095869,2.778673 -2.874223,3.773068 -0.994236,1.02684 -6.879641,7.657944 -6.167884,7.049648 -1.292899,1.235403 -5.717368,5.476022 -5.717368,5.476022 0,0 -4.323294,-3.985179 -5.928388,-5.591297 C 14.037321,47.920078 10.708239,43.994015 9.6976253,42.770306 8.6870114,41.546601 8.5086687,40.900753 6.8441265,38.818752 5.8958518,37.63265 4.1376268,34.24638 3.0745121,32.156026 2.9037625,31.86435 2.7398218,31.568267 2.5826899,31.268005 2.5509386,31.228498 2.5238331,31.18779 2.5044312,31.145084 2.4575955,31.041974 2.4164305,30.951055 2.3805569,30.87146 0.95511134,28.003558 0.15221914,24.771643 0.15221914,21.351725 c 0,-11.829154 9.58943056,-21.41858234 21.41858286,-21.41858234 11.829152,0 21.418583,9.58942834 21.418583,21.41858234 0,3.457576 -0.820406,6.72314 -2.275417,9.614477 z M 21.52596,1.5031489 c -10.866018,0 -19.6746717,8.8086521 -19.6746717,19.6746741 0,10.866016 8.8086537,19.674669 19.6746717,19.674669 10.866018,0 19.674672,-8.808648 19.674672,-19.674669 0,-10.866022 -8.808654,-19.6746741 -19.674672,-19.6746741 z" /><g transform="translate(6.5,6) scale(0.060546875)"><path d="M32 384h272v32H32zM400 384h80v32h-80zM384 447.5c0 17.949-14.327 32.5-32 32.5-17.673 0-32-14.551-32-32.5v-95c0-17.949 14.327-32.5 32-32.5 17.673 0 32 14.551 32 32.5v95z"></path><g><path d="M32 240h80v32H32zM208 240h272v32H208zM192 303.5c0 17.949-14.327 32.5-32 32.5-17.673 0-32-14.551-32-32.5v-95c0-17.949 14.327-32.5 32-32.5 17.673 0 32 14.551 32 32.5v95z"></path></g><g><path d="M32 96h272v32H32zM400 96h80v32h-80zM384 159.5c0 17.949-14.327 32.5-32 32.5-17.673 0-32-14.551-32-32.5v-95c0-17.949 14.327-32.5 32-32.5 17.673 0 32 14.551 32 32.5v95z"></path></g></g></svg>
</div>
<div id="imageContainer"></div>
关于javascript - SVG 渲染成 Canvas ,在视网膜显示器上模糊,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41763580/
我可以使用两种方法添加一个 child ,一种是 Canvas.AddVisualChild(Visual); Canvas.AddLogicalChild(Visual); 我在视觉对象的 Draw
在过去的几周里,我一直在尝试各种方法,试图找到将 BDD 用于依赖于 HTML5 Canvas 元素以及用户与之交互的 Web 应用程序的最佳方法。 我一直在使用 Jasmine 和 Cucumber
我正在尝试完成撤消/重做。我正在使用loadFromJSON(...)从我存储在数组中的 Canvas 状态重新构建 Canvas 。基本上,我的想法是破坏现有的 Canvas 并重新构建 Canva
我正在尝试在 Canvas 上设置简单的放大/缩小功能。我正在使用 KineticJS 处理触摸事件并在 Canvas 中绘图,但无法实现缩放。 KinteicJS 有一个类似的例子,但它们总是在中心
我正在使用 processing.js 在 javascript 中开发一个画笔应用程序 它正在使用 Canvas 对象。我想在 Canvas 的背景中保留一个图像。在前景中画一些东西。在保存时,我只
您好,我想为 discord.js Bot 安装 Canvas 。 当我尝试使用以下命令安装 Canvas 时npm install canvas我收到以下错误: pi@server:~/Bots/D
我正在尝试使用 Canvas 和动力学的组合来构建填充图案,但在尝试获得连续线时遇到了问题。 此 jsfiddle显示了到目前为止我所拥有的,但是因为我的重复模式是正方形,角会影响线条,我尝试使用 l
我正在开发一个 webassembly 程序。 我可以使用 emscripten_set_canvas_size 设置 Canvas 大小(我一直读到我需要切换到新的 API,因为这个 API 会贬值
您好,我已经为第一个 Canvas 中的第一个图像创建了一个圆形表单,但我没有成功使用第一个 Canvas 的 dataURL 并将其添加到第二个 Canvas 中。 这是我的 fiddle :htt
问题在于不同浏览器之间的不一致。 使用Dart Chrome,JS Chrome,JS Opera运行 双击可以进入和退出全屏 m_oCanvas.width =(window.screen.widt
我正在使用Flutter框架和Dart开发图像编辑器,因此无法将矩阵滤镜应用于 Canvas 。 我正在尝试使用“Paint”类和“canvas.drawPaint(paint)”函数将矩阵过滤器应用
如果在已经具有非整数比例因子的 Canvas 上绘制图像,我会遇到 Canvas 上下文drawImage()方法的问题。似乎这样的图像以一种奇怪的方式被剪切(有时图像的最右边的部分被剪切,有时是最底
Canvas 的“宽度”属性值有限制吗? 在下面的示例中,我在 ScrolledWindow 中创建一个 Canvas。 # Packages package require BWidget # Ma
我正在尝试制作类似于 this article 底部的效果的文本效果 我建议的方法是: 制作两个 Canvas ,一个是可见的,另一个是不可见的我用它作为缓冲区。 在缓冲区 Canvas 上绘制一些文
例如var new = canvas.toDataURL("image/png"); 我希望这个新变量中存在的 base64 显示到存在的第二个 Canvas 元素中。但是它不使用 drawimage
有人有使用这两个 Node.js 库中的一个或两个的经验吗?很想知道每个人的成功或困难。 最佳答案 LearnBoost是社区中最多产的 Node 模块开发人员之一,因此我选择使用 node-canv
如何知道 Canvas 运行的是“WebGL”还是普通 Canvas ? 通过检查源代码,我发现这两种情况都是 Canvas 。 最佳答案 这真的取决于你想如何去发现。 例如你可以这样调用 `getC
在 Canvas 上绘图非常好。甚至橡皮擦也能正常工作。问题是,当 Canvas 保存为图像时,它绘制的是黑线而不是橡皮擦。 为了更好地理解,我添加了屏幕截图和代码。 1。在删除绘图时 - 一个。源代
我正在尝试为 Canvas 附加鼠标悬停和鼠标移出事件: 默认 Canvas 是函数drawcircle的 Canvas 。 如果用户越过 Canvas ,应将其更改为drawEllipse的 Can
我正在使用 Three.js 构建一个简单的 2D 游戏。我只使用世界的 X 和 Y 位置来移动对象,将它们的 z 位置保留为零。我使用禁用旋转的 TrackballControls,以允许使用右键单
我是一名优秀的程序员,十分优秀!