尘世天使(canvas画布抽丝效果)
本帖最后由 马黑黑 于 2024-4-24 12:54 编辑 <br /><br /><style>#mydiv { margin: 20px 0; left: calc(50% - 81px); transform: translateX(-50%); width: fit-content; height: fit-content; overflow: hidden; pointer-events: none; position: relative; }
#mydiv::after { position: absolute; content: url('https://638183.freep.cn/638183/small/f01.png'); left: 20px; top: 20px; mix-blend-mode: multiply; cursor: pointer; pointer-events: auto; animation: rot 6s linear infinite var(--state); }
#canv { positon: absolute; background: #333; border: 1px solid gray; }
@keyframes rot { to { transform: rotate(360deg); } }
</style>
<div id="mydiv">
<audio id="aud" src="https://music.163.com/song/media/outer/url?id=1316295691" autoplay loop></audio>
<canvas id="canv"></canvas>
</div>
<script>
var ctx = canv.getContext('2d');
var img = new Image();
img.crossOrigin = 'anonymous';
img.onload = () => {
ww = canv.width = img.width;
hh = canv.height = img.height;
ctx.drawImage(img, 0, 0);
reDraw(ctx, ctx.getImageData(0,0,ww,hh));
};
img.src = 'https://638183.freep.cn/638183/t24/2/angel.jpg';
var reDraw = (context, data) => {
for(var i = 0; i < data.data.length; i += 4) {
if(i % 60 === 0) data.data = 100;
}
ctx.clearRect(0, 0, ww, hh);
context.clearRect(0,0,ww,hh);
context.putImageData(data,0,0);
};
aud.onplaying = aud.onpause = () => mydiv.style.setProperty('--state', aud.paused ? 'paused' : 'running');
mydiv.onclick = () => aud.paused ? aud.play() : aud.pause();
</script> <style>
.mum { position: relative; margin: 0; padding: 10px; font: normal 16px/20px Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; color: black; background: rgba(240, 240, 240,.95); box-shadow: 2px 2px 4px gray; border: thick groove lightblue; border-radius: 6px; }
.mum ::selection { background-color: rgba(0,100,100,.35); }
.mum div { margin: 0; padding: 0; }
.mum cl-cd { display: block; position: relative; margin: 0 0 0 50px; padding: 0 0 0 10px; white-space: pre-wrap; overflow-wrap: break-word; border-left: 1px solid silver; }
.mum cl-cd::before { position: absolute; content: attr(data-idx); width: 50px; color: gray; text-align: right; transform: translate(-70px); }
.tRed { color: red; }
.tBlue { color: blue; }
.tGreen { color: green; }
.tDarkRed { color: darkred; }
.tMagenta { color: magenta; }
</style>
<h2>代码</h2>
<div class='mum'>
<cl-cd data-idx="1"><<span class="tDarkRed">style</span>></cl-cd>
<cl-cd data-idx="2">#mydiv { <span class="tBlue">margin:</span> 20px 0; <span class="tBlue">left:</span> calc(50% - 81px); <span class="tBlue">transform:</span> translateX(-50%); <span class="tBlue">width:</span> fit-content; <span class="tBlue">height:</span> fit-content; <span class="tBlue">overflow:</span> hidden; <span class="tBlue">pointer-events:</span> none; <span class="tBlue">position:</span> relative; }</cl-cd>
<cl-cd data-idx="3">#mydiv::after { <span class="tBlue">position:</span> absolute; <span class="tBlue">content:</span> url(<span class="tMagenta">'https://638183.freep.cn/638183/small/f01.png'</span>); <span class="tBlue">left:</span> 20px; <span class="tBlue">top:</span> 20px; <span class="tBlue">mix-blend-mode:</span> multiply; <span class="tBlue">cursor:</span> pointer; <span class="tBlue">pointer-events:</span> auto; <span class="tBlue">animation:</span> rot 6s linear infinite <span class="tBlue">var</span>(--state); }</cl-cd>
<cl-cd data-idx="4">#canv { <span class="tBlue">positon:</span> absolute; <span class="tBlue">background:</span> #333; <span class="tBlue">border:</span> 1px solid gray; }</cl-cd>
<cl-cd data-idx="5">@keyframes rot { to { <span class="tBlue">transform:</span> rotate(360deg); } }</cl-cd>
<cl-cd data-idx="6"><<span class="tDarkRed">/style</span>></cl-cd>
<cl-cd data-idx="7"> </cl-cd>
<cl-cd data-idx="8"><<span class="tDarkRed">div</span> <span class="tRed">id</span>=<span class="tMagenta">"mydiv"</span>></cl-cd>
<cl-cd data-idx="9"> <<span class="tDarkRed">audio</span> <span class="tRed">id</span>=<span class="tMagenta">"aud"</span> src=<span class="tMagenta">"https://music.163.com/song/media/outer/url?<span class="tRed">id</span>=1316295691"</span> autoplay loop><<span class="tDarkRed">/audio</span>></cl-cd>
<cl-cd data-idx="10"> <<span class="tDarkRed">canvas</span> <span class="tRed">id</span>=<span class="tMagenta">"canv"</span>><<span class="tDarkRed">/canvas</span>></cl-cd>
<cl-cd data-idx="11"><<span class="tDarkRed">/div</span>></cl-cd>
<cl-cd data-idx="12"> </cl-cd>
<cl-cd data-idx="13"><<span class="tDarkRed">script</span>></cl-cd>
<cl-cd data-idx="14"><span class="tBlue">var</span> ctx = canv.getContext(<span class="tMagenta">'2d'</span>);</cl-cd>
<cl-cd data-idx="15"> </cl-cd>
<cl-cd data-idx="16"><span class="tBlue">var</span> img = <span class="tBlue">new</span> Image();</cl-cd>
<cl-cd data-idx="17">img.crossOrigin = <span class="tMagenta">'anonymous'</span>;</cl-cd>
<cl-cd data-idx="18">img.onload = () => {</cl-cd>
<cl-cd data-idx="19"> ww = canv.width = img.width;</cl-cd>
<cl-cd data-idx="20"> hh = canv.height = img.height;</cl-cd>
<cl-cd data-idx="21"> ctx.drawImage(img, 0, 0);</cl-cd>
<cl-cd data-idx="22"> reDraw(ctx, ctx.getImageData(0,0,ww,hh));</cl-cd>
<cl-cd data-idx="23">};</cl-cd>
<cl-cd data-idx="24">img.src = <span class="tMagenta">'https://638183.freep.cn/638183/t24/2/angel.jpg'</span>;</cl-cd>
<cl-cd data-idx="25"> </cl-cd>
<cl-cd data-idx="26"><span class="tBlue">var</span> reDraw = (context, data) => {</cl-cd>
<cl-cd data-idx="27"> <span class="tBlue">for</span>(<span class="tBlue">var</span> i = 0; i < data.data.length; i += 4) {</cl-cd>
<cl-cd data-idx="28"> <span class="tBlue">if</span>(i % 60 === 0) data.data = 100;</cl-cd>
<cl-cd data-idx="29"> }</cl-cd>
<cl-cd data-idx="30"> ctx.clearRect(0, 0, ww, hh);</cl-cd>
<cl-cd data-idx="31"> context.clearRect(0,0,ww,hh);</cl-cd>
<cl-cd data-idx="32"> context.putImageData(data,0,0);</cl-cd>
<cl-cd data-idx="33">};</cl-cd>
<cl-cd data-idx="34"> </cl-cd>
<cl-cd data-idx="35">aud.onplaying = aud.onpause = () => mydiv.style.setProperty(<span class="tMagenta">'--state'</span>, aud.paused ? <span class="tMagenta">'paused'</span> : <span class="tMagenta">'running'</span>);</cl-cd>
<cl-cd data-idx="36">mydiv.onclick = () => aud.paused ? aud.play() : aud.pause();</cl-cd>
<cl-cd data-idx="37"> </cl-cd>
<cl-cd data-idx="38"><<span class="tDarkRed">/script</span>></cl-cd>
</div>
实现原理:获取图片所有像素信息,按一定间隔更改alpha通道值,然后刷新画布。
画布设置背景色,背景色将影响丝线的颜色。代码在 04 行;
遍历图片像素,下标被 60 整除的,则将该像素的 alpha 值改为 100。在canvas画布,alpha 值取值范围是 0~255,取 100 则是大半透明,可根据需要设置该值(全透明也是可以的)。像素改 alpha 值的条件依据被整除数,不同的被整除数会得到不同的丝线效果。代码在 28 行。 超级好看的效果呀。。PS的抽丝效果。。。代码实现的。。{:4_199:} background: green;小点点的颜色改为绿色。。。
if(i % 3 === 0) data.data = 20;百分号后的数字改为10以下,抽丝效果比PS图案实现的更漂亮 这效果也太漂亮了!我抽空试试! 马黑黑 发表于 2024-4-24 12:55
.mum { position: relative; margin: 0; padding: 10px; font: normal 16px/20px Consolas, Monaco, 'And ...
i += 60 不就省去了 i%60 的判断 美女漂亮,效果更漂亮~~{:4_190:} 朵拉 发表于 2024-4-24 16:27
美女漂亮,效果更漂亮~~
{:4_191:} 南无月 发表于 2024-4-24 13:07
超级好看的效果呀。。PS的抽丝效果。。。代码实现的。。
和ps原理差不多的吧 起个网名好难 发表于 2024-4-24 15:20
i += 60 不就省去了 i%60 的判断
这个思路好{:4_190:} 亚伦影音工作室 发表于 2024-4-24 14:40
这效果也太漂亮了!我抽空试试!
{:4_191:} 南无月 发表于 2024-4-24 13:09
background: green;小点点的颜色改为绿色。。。
if(i % 3 === 0) data.data = 20;百分号后的数字改为10以 ...
实践出真知 马黑黑 发表于 2024-4-24 17:47
和ps原理差不多的吧
原理不知道。。
反正从PS里常用的抽丝功能,再用代码见到就感觉熟悉,且效果比图案填充更好一些。。
着实好看。。。 马黑黑 发表于 2024-4-24 17:50
实践出真知
等有空再试试别的网格。。
感觉比PS图片上加效果更方便 ,因为改数字就有不同的效果了 南无月 发表于 2024-4-24 18:08
等有空再试试别的网格。。
感觉比PS图片上加效果更方便 ,因为改数字就有不同的效果了
然后存为 南无月 发表于 2024-4-24 18:07
原理不知道。。
反正从PS里常用的抽丝功能,再用代码见到就感觉熟悉,且效果比图案填充更好一些。。
着 ...
现在是遍历原始数组,如果遍历图片的XY坐标会有更多可能 这个不仅让图片抽丝,连按钮都一起抽丝了,有趣{:4_199:} 用代码去改变图片的展示,这个太神奇了,得到的效果也特别美妙{:4_187:} 马黑黑 发表于 2024-4-24 18:13
然后存为
{:4_199:}对哦,可以当工具使用。整好图片直接另存。