如何解决像素化整个网页
我了解如何缩放小画布以制作具有粗大而不是模糊像素的大画布。
有什么方法可以使整个网页显示为 2x2 或 3x3 像素?即用最近邻缩放放大它。我想使用普通的 HTML,但将其像素化以获得仿 8 位外观。
解决方法
好主意。如果你不关心性能,我想这不是太难。
编辑:我花了一整天的时间进行研究,做了大量的测试并编写了自己的小例子。这些是我的结果:
选项 1:静态 SVG 过滤器
感谢Amaury Hanser。
您可以定义一个 svg 过滤器并在您的 css 中使用它:(参见 https://stackoverflow.com/a/66625778/6292230)
这个解决方案在各方面都很漂亮。
然而,苹果不喜欢你。某些过滤器或属性在 macOS 和 iOS 上Safari 不支持。例如:当用作 css 过滤器时,Safari 会忽略 x、y、width、height,这会使大多数解决方案无用。如果您可以控制环境(例如 WebView、Electron 等),这是最好的解决方案。
选项 2:动态 SVG 过滤器
计算工作:每个视口调整大小/页面加载一次
这应该可以跨浏览器工作。在最新的 Safari、Chrome 和 Firefox (macOS) 上测试。 您可以使用选项 1 中所述的类似技术。 但是,您必须将点阵渲染到屏幕外画布并将其注入 svg 过滤器。每次视口大小发生变化时(例如在调整大小事件之后),您都必须重新计算。
工作代码和框示例:https://codesandbox.io/s/pixelate-page-demo-dt6w0?file=/src/index.js (如果未显示效果,请单击右侧 iframe 中的重新加载按钮)
- 在你的身体内创建一个空的 svg 过滤器
<body>
<svg>
<filter
id="pixelate"
x="0"
y="0"
width="700"
height="900"
filterUnits="userSpaceOnUse"
></filter>
</svg>
</body>
- 动态创建和注入 svg 过滤器,如下所示
function pixelate(tileSize = 10,sigmaGauss = 2) {
tileSize = tileSize < 1 ? 1 : tileSize;
sigmaGauss = sigmaGauss < 1 ? 1 : sigmaGauss;
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
ctx.fillStyle = "black";
ctx.fillRect(0,canvas.width,canvas.height);
// only to make the output visible
// document.body.appendChild(canvas);
const rows = canvas.height / tileSize;
const cols = canvas.width / tileSize;
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
ctx.fillStyle = "white";
ctx.fillRect(
c * tileSize - 1 + Math.floor(tileSize / 2),r * tileSize - 1 + Math.floor(tileSize / 2),1,1
);
}
}
const pixelate = document.getElementById("pixelate");
pixelate.innerHTML = "";
const blur = document.createElementNS(
"http://www.w3.org/2000/svg","feGaussianBlur"
);
blur.setAttribute("in","SourceGraphic");
blur.setAttribute("stdDeviation",sigmaGauss);
blur.setAttribute("result","blurred");
const hmap = document.createElementNS(
"http://www.w3.org/2000/svg","feImage"
);
const hmapUrl = canvas.toDataURL();
hmap.setAttribute("href",hmapUrl);
hmap.setAttribute("result","hmap");
const blend = document.createElementNS(
"http://www.w3.org/2000/svg","feBlend"
);
// blend.setAttribute("mode","lighten");
blend.setAttribute("mode","multiply");
blend.setAttribute("in","blurred");
blend.setAttribute("in2","hmap");
const morph = document.createElementNS(
"http://www.w3.org/2000/svg","feMorphology"
);
morph.setAttribute("operator","dilate");
morph.setAttribute("radius",tileSize / 2);
pixelate.setAttribute("width",canvas.width);
pixelate.setAttribute("height",canvas.height);
pixelate.appendChild(blur);
pixelate.appendChild(hmap);
pixelate.appendChild(blend);
pixelate.appendChild(morph);
}
- 页面加载/视口调整大小调用后
pixelate(5,1); // 5 = tileSize,1 = std deviation gaussian blur
- 添加CSS。 提示:不要使用
display: none;
隐藏 svg,因为它会在 Firefox 中中断
html {
filter: url(#pixelate);
}
svg {
position: absolute;
height: 0;
}
选项 3:叠加画布
计算工作:每次 DOM 更改
如果没有工作示例,我会这样做:
-
将页面渲染到 DOM
-
将您的页面渲染到画布上(请参阅 html2canvas: http://html2canvas.hertzen.com 或更好的 rasterizeHTML: https://github.com/cburgmer/rasterizeHTML.js)
-
覆盖画布
position: absolute; left: 0; top: 0; width: 100%; z-index: 100;
-
不要捕捉画布上的点击,这样下面呈现的 DOM 上的按钮/链接就会起作用
pointer-events: none;
-
在不平滑图像的情况下缩放画布(请参阅此处:How to pixelate an image with canvas and javascript)
尽量避免动态重新渲染以获得最佳性能。
选项 4:WebGL 着色器
计算量:每一帧
目前最酷的方法是通过 WebGL 渲染您的网站并使用着色器来创建所需的效果。
- 您可以扩展选项 3,渲染全尺寸画布(请记住为视网膜设备渲染双倍尺寸),获取 WebGl 上下文并附加着色器
- 或者,您可以使用 HTML GL (http://htmlgl.com/)。我不推荐它,因为它似乎没有维护,也不支持视网膜设备(=> 因此一切都会变得模糊)
您可以为此使用 svg 过滤器。
请注意,此解决方案不是跨浏览器的。
正如@adroste 所说,它不适用于 Safari (Mac/iOS) 或更旧的浏览器。
您需要调整它以使其看起来像您想要的那样,但这里有一个简单的例子:
html { filter: url("#pixelate") }
svg { display: block }
h1 { color: red }
h2 { color: blue}
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="0" height="0">
<defs>
<filter id="pixelate" x="0" y="0">
<feFlood x="2" y="2" height="1" width="1"/>
<feComposite width="5" height="5"/>
<feTile result="a"/>
<feComposite in="SourceGraphic" in2="a"
operator="in"/>
<feMorphology operator="dilate"
radius="2.5"/>
</filter>
</defs>
</svg>
<h1>
Lorem ipsum,dolor sit amet consectetur adipisicing elit.
</h1>
<h2>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Reprehenderit,fuga.
</h2>
<p>
Lorem ipsum,dolor sit amet consectetur adipisicing elit. Doloribus dolorem,maxime recusandae modi adipisci,praesentium qui aliquam consequatur tempore fugiat quasi minus necessitatibus excepturi enim sapiente quibusdam deleniti perferendis quisquam?
</p>
你或许可以用不同的滤镜来达到这个效果。
您可以在 MDN docs 上了解有关 svf 过滤器的更多信息。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。