马黑黑 发表于 2024-4-24 12:53

尘世天使(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>

马黑黑 发表于 2024-4-24 12:55

<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">&lt;<span class="tDarkRed">style</span>&gt;</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">&lt;<span class="tDarkRed">/style</span>&gt;</cl-cd>
<cl-cd data-idx="7">&nbsp;</cl-cd>
<cl-cd data-idx="8">&lt;<span class="tDarkRed">div</span> <span class="tRed">id</span>=<span class="tMagenta">"mydiv"</span>&gt;</cl-cd>
<cl-cd data-idx="9">&nbsp; &nbsp; &lt;<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&gt;&lt;<span class="tDarkRed">/audio</span>&gt;</cl-cd>
<cl-cd data-idx="10">&nbsp; &nbsp; &lt;<span class="tDarkRed">canvas</span> <span class="tRed">id</span>=<span class="tMagenta">"canv"</span>&gt;&lt;<span class="tDarkRed">/canvas</span>&gt;</cl-cd>
<cl-cd data-idx="11">&lt;<span class="tDarkRed">/div</span>&gt;</cl-cd>
<cl-cd data-idx="12">&nbsp;</cl-cd>
<cl-cd data-idx="13">&lt;<span class="tDarkRed">script</span>&gt;</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">&nbsp;</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 = () =&gt; {</cl-cd>
<cl-cd data-idx="19">&nbsp; &nbsp; ww = canv.width = img.width;</cl-cd>
<cl-cd data-idx="20">&nbsp; &nbsp; hh = canv.height = img.height;</cl-cd>
<cl-cd data-idx="21">&nbsp; &nbsp; ctx.drawImage(img, 0, 0);</cl-cd>
<cl-cd data-idx="22">&nbsp; &nbsp; 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">&nbsp;</cl-cd>
<cl-cd data-idx="26"><span class="tBlue">var</span> reDraw = (context, data) =&gt; {</cl-cd>
<cl-cd data-idx="27">&nbsp; &nbsp; <span class="tBlue">for</span>(<span class="tBlue">var</span> i = 0; i &lt; data.data.length; i += 4) {</cl-cd>
<cl-cd data-idx="28">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">if</span>(i % 60 === 0) data.data = 100;</cl-cd>
<cl-cd data-idx="29">&nbsp; &nbsp; }</cl-cd>
<cl-cd data-idx="30">&nbsp; &nbsp; ctx.clearRect(0, 0, ww, hh);</cl-cd>
<cl-cd data-idx="31">&nbsp; &nbsp; context.clearRect(0,0,ww,hh);</cl-cd>
<cl-cd data-idx="32">&nbsp; &nbsp; context.putImageData(data,0,0);</cl-cd>
<cl-cd data-idx="33">};</cl-cd>
<cl-cd data-idx="34">&nbsp;</cl-cd>
<cl-cd data-idx="35">aud.onplaying = aud.onpause = () =&gt; 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 = () =&gt; aud.paused ? aud.play() : aud.pause();</cl-cd>
<cl-cd data-idx="37">&nbsp;</cl-cd>
<cl-cd data-idx="38">&lt;<span class="tDarkRed">/script</span>&gt;</cl-cd>
</div>

马黑黑 发表于 2024-4-24 13:02

实现原理:获取图片所有像素信息,按一定间隔更改alpha通道值,然后刷新画布。

画布设置背景色,背景色将影响丝线的颜色。代码在 04 行;

遍历图片像素,下标被 60 整除的,则将该像素的 alpha 值改为 100。在canvas画布,alpha 值取值范围是 0~255,取 100 则是大半透明,可根据需要设置该值(全透明也是可以的)。像素改 alpha 值的条件依据被整除数,不同的被整除数会得到不同的丝线效果。代码在 28 行。

南无月 发表于 2024-4-24 13:07

超级好看的效果呀。。PS的抽丝效果。。。代码实现的。。{:4_199:}

南无月 发表于 2024-4-24 13:09

background: green;小点点的颜色改为绿色。。。
if(i % 3 === 0) data.data = 20;百分号后的数字改为10以下,抽丝效果比PS图案实现的更漂亮

亚伦影音工作室 发表于 2024-4-24 14:40

这效果也太漂亮了!我抽空试试!

起个网名好难 发表于 2024-4-24 15:20

马黑黑 发表于 2024-4-24 12:55
.mum { position: relative; margin: 0; padding: 10px; font: normal 16px/20px Consolas, Monaco, 'And ...

i += 60 不就省去了 i%60 的判断

朵拉 发表于 2024-4-24 16:27

美女漂亮,效果更漂亮~~{:4_190:}

马黑黑 发表于 2024-4-24 17:45

朵拉 发表于 2024-4-24 16:27
美女漂亮,效果更漂亮~~

{:4_191:}

马黑黑 发表于 2024-4-24 17:47

南无月 发表于 2024-4-24 13:07
超级好看的效果呀。。PS的抽丝效果。。。代码实现的。。

和ps原理差不多的吧

马黑黑 发表于 2024-4-24 17:49

起个网名好难 发表于 2024-4-24 15:20
i += 60 不就省去了 i%60 的判断

这个思路好{:4_190:}

马黑黑 发表于 2024-4-24 17:49

亚伦影音工作室 发表于 2024-4-24 14:40
这效果也太漂亮了!我抽空试试!

{:4_191:}

马黑黑 发表于 2024-4-24 17:50

南无月 发表于 2024-4-24 13:09
background: green;小点点的颜色改为绿色。。。
if(i % 3 === 0) data.data = 20;百分号后的数字改为10以 ...

实践出真知

南无月 发表于 2024-4-24 18:07

马黑黑 发表于 2024-4-24 17:47
和ps原理差不多的吧

原理不知道。。
反正从PS里常用的抽丝功能,再用代码见到就感觉熟悉,且效果比图案填充更好一些。。
着实好看。。。

南无月 发表于 2024-4-24 18:08

马黑黑 发表于 2024-4-24 17:50
实践出真知

等有空再试试别的网格。。
感觉比PS图片上加效果更方便 ,因为改数字就有不同的效果了

马黑黑 发表于 2024-4-24 18:13

南无月 发表于 2024-4-24 18:08
等有空再试试别的网格。。
感觉比PS图片上加效果更方便 ,因为改数字就有不同的效果了

然后存为

马黑黑 发表于 2024-4-24 18:14

南无月 发表于 2024-4-24 18:07
原理不知道。。
反正从PS里常用的抽丝功能,再用代码见到就感觉熟悉,且效果比图案填充更好一些。。
着 ...

现在是遍历原始数组,如果遍历图片的XY坐标会有更多可能

红影 发表于 2024-4-24 20:21

这个不仅让图片抽丝,连按钮都一起抽丝了,有趣{:4_199:}

红影 发表于 2024-4-24 20:21

用代码去改变图片的展示,这个太神奇了,得到的效果也特别美妙{:4_187:}

南无月 发表于 2024-4-24 20:24

马黑黑 发表于 2024-4-24 18:13
然后存为

{:4_199:}对哦,可以当工具使用。整好图片直接另存。
页: [1] 2 3 4 5 6
查看完整版本: 尘世天使(canvas画布抽丝效果)