9块9包邮的canvas放大镜
本帖最后由 马黑黑 于 2024-4-10 14:23 编辑 <br /><br /><style>.outer { left: calc(50% - 81px); transform: translate(-50%, 0); width: fit-content; height: fit-content; text-align: center; background: lightblue;position: relative; z-index: 1; }
.canv { display: block; cursor: crosshair; }
.canv:nth-of-type(2) { position: absolute; pointer-events: none; border-radius: 50%; }
.tb input { margin-left: 10px; }
</style>
<div class="outer">
<canvas class="canv"></canvas>
<canvas class="canv" width="150" height="150"></canvas>
<p class="tb">
<label for="URI">图片:</label>
<input id="URI" type="text" size="100" value="" placeholder="请输入图片地址" />
<input id="btnOkey" type="button" value="中" />
</p>
</div>
<script type="text/javascript">
var beShown = false, mTimer;
var canvs = document.querySelectorAll('.canv');
var size = {w: 300, h: 150}, msize = {w: canvs.width, h: canvs.height};
var ctx1 = canvs.getContext('2d'), ctx2 = canvs.getContext('2d');
var loadImage = (url) => {
var promise = new Promise((resolve, reject) => {
var img = new Image();
img.onload = () => {
var ele = img;
resolve(ele);
};
img.onerror = (err) => {
reject(err);
};
img.src = url;
});
return promise;
};
var update = (pic) => {
loadImage(pic).then(e => {
size.w = e.width;
size.h = e.height;
canvs.width = size.w / 2;
canvs.height = size.h / 2;
ctx1.clearRect(0, 0, size.w / 2, size.h / 2);
ctx1.drawImage(e, 0, 0, size.w / 2, size.h / 2);
}).catch(e => {
ctx1.save();
ctx1.font = 'bold 40px sans-serif';
ctx1.textBaseline = 'middle';
ctx1.textAlign = 'center';
ctx1.globalCompositeOperation = 'xor';
ctx1.fillText('图片加载失败', size.w / 4, size.h / 4);
ctx1.restore();
});
};
canvs.onmousemove = (e) => {
clearTimeout(mTimer);
var x = e.offsetX, y = e.offsetY;
if(x - 25 < 0) x = 25;
if(size.w - x < 25) x = size.w - 25;
if(y - 25 < 0) y = 25;
if(size.h - y < 25) y = size.h - 25;
canvs.style.left = x - msize.w / 2 + 'px';
canvs.style.top = y - msize.h / 2 + 'px';
ctx2.clearRect(0, 0, msize.w, msize.h);
ctx2.drawImage(canvs, x - 25, y - 25, 50, 50, 0, 0, msize.w, msize.h);
mTimer = setTimeout('ctx2.clearRect(0, 0, msize.w, msize.h)', 3000);
};
canvs.onmouseout = () => ctx2.clearRect(0, 0, msize.w, msize.h);
btnOkey.onclick = () => {
if(URI.value) update(URI.value.trim());
}
URI.onclick = () => URI.select();
URI.onkeydown = (e) => {
e = window.event || e;
var code = e.keyCode || e.which || e.charCode;
if(code === 13) btnOkey.click();
};
var pic = 'https://638183.freep.cn/638183/t24/webp/magnifier.webp';
update(pic);
</script> 本帖最后由 马黑黑 于 2024-4-10 14:03 编辑 <br /><br /><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>
<p>一楼,图片会被缩小一半显示。以下提供的代码则是按图片原始尺寸显示,可将代码存为本地HTML文档测试:<br><br></p>
<div class='mum'>
<cl-cd data-idx="1"><!DOCTYPE html></cl-cd>
<cl-cd data-idx="2"><<span class="tDarkRed">html</span> lang=<span class="tMagenta">"en"</span> xmlns=<span class="tMagenta">"http://www.w3.org/1999/xhtml"</span>></cl-cd>
<cl-cd data-idx="3"><<span class="tDarkRed">head</span>></cl-cd>
<cl-cd data-idx="4"> <<span class="tDarkRed">meta</span> charset=<span class="tMagenta">"utf-8"</span> /></cl-cd>
<cl-cd data-idx="5"> <<span class="tDarkRed">title</span>>放大镜<<span class="tDarkRed">/title</span>></cl-cd>
<cl-cd data-idx="6"> <<span class="tDarkRed">meta</span> name=<span class="tMagenta">"author"</span> content=<span class="tMagenta">""</span> /></cl-cd>
<cl-cd data-idx="7"> <<span class="tDarkRed">meta</span> name=<span class="tMagenta">"keywords"</span> content=<span class="tMagenta">""</span> /></cl-cd>
<cl-cd data-idx="8"> <<span class="tDarkRed">meta</span> name=<span class="tMagenta">"description"</span> content=<span class="tMagenta">""</span> /></cl-cd>
<cl-cd data-idx="9"> <<span class="tDarkRed">style</span>></cl-cd>
<cl-cd data-idx="10"> #wrapper { <span class="tBlue">margin:</span> 20px auto; <span class="tBlue">width:</span> fit-content; <span class="tBlue">height:</span> fit-content; <span class="tBlue">position:</span> relative; }</cl-cd>
<cl-cd data-idx="11"> #canv { <span class="tBlue">position:</span> absolute; <span class="tBlue">transform:</span> scale(<span class="tBlue">var</span>(--size)); <span class="tBlue">border-radius:</span> 50%; <span class="tBlue">pointer-events:</span> none; <span class="tBlue">--size:</span> 1; }</cl-cd>
<cl-cd data-idx="12"> <<span class="tDarkRed">/style</span>></cl-cd>
<cl-cd data-idx="13"><<span class="tDarkRed">/head</span>></cl-cd>
<cl-cd data-idx="14"><<span class="tDarkRed">body</span>></cl-cd>
<cl-cd data-idx="15"> </cl-cd>
<cl-cd data-idx="16"><<span class="tDarkRed">div</span> <span class="tRed">id</span>=<span class="tMagenta">"wrapper"</span>></cl-cd>
<cl-cd data-idx="17"> <<span class="tDarkRed">img</span> <span class="tRed">id</span>=<span class="tMagenta">"img1"</span> src=<span class="tMagenta">"https://img.zcool.cn/community/01e8bf5c00a77aa801209252bda875.jpg@1280w_1l_2o_100sh.jpg"</span> alt=<span class="tMagenta">""</span> /></cl-cd>
<cl-cd data-idx="18"> <<span class="tDarkRed">canvas</span> <span class="tRed">id</span>=<span class="tMagenta">"canv"</span> width=<span class="tMagenta">"200"</span> height=<span class="tMagenta">"200"</span>><<span class="tDarkRed">/canvas</span>></cl-cd>
<cl-cd data-idx="19"><<span class="tDarkRed">/div</span>></cl-cd>
<cl-cd data-idx="20"> </cl-cd>
<cl-cd data-idx="21"><<span class="tDarkRed">script</span> type=<span class="tMagenta">"text/javascript"</span>></cl-cd>
<cl-cd data-idx="22"> </cl-cd>
<cl-cd data-idx="23"><span class="tBlue">let</span> ww, hh, beShown = false, mTimer;</cl-cd>
<cl-cd data-idx="24"><span class="tBlue">let</span> ctx = canv.getContext(<span class="tMagenta">'2d'</span>);</cl-cd>
<cl-cd data-idx="25"> </cl-cd>
<cl-cd data-idx="26"><span class="tBlue">let</span> getSize = (img) => {</cl-cd>
<cl-cd data-idx="27"> ww = img.width;</cl-cd>
<cl-cd data-idx="28"> hh = img.height;</cl-cd>
<cl-cd data-idx="29">};</cl-cd>
<cl-cd data-idx="30"> </cl-cd>
<cl-cd data-idx="31">img1.onload = (callback) => getSize(img1);</cl-cd>
<cl-cd data-idx="32"> </cl-cd>
<cl-cd data-idx="33">img1.onmousemove = (e) => {</cl-cd>
<cl-cd data-idx="34"> clearTimeout(mTimer);</cl-cd>
<cl-cd data-idx="35"> img1.style.cursor = <span class="tMagenta">'crosshair'</span>;</cl-cd>
<cl-cd data-idx="36"> <span class="tBlue">let</span> x = e.offsetX, y = e.offsetY;</cl-cd>
<cl-cd data-idx="37"> <span class="tBlue">if</span>(x - 25 < 0) x = 25;</cl-cd>
<cl-cd data-idx="38"> <span class="tBlue">if</span>(ww - x < 25) x = ww - 25;</cl-cd>
<cl-cd data-idx="39"> <span class="tBlue">if</span>(y - 25 < 0) y = 25;</cl-cd>
<cl-cd data-idx="40"> <span class="tBlue">if</span>(hh - y < 25) y = hh - 25;</cl-cd>
<cl-cd data-idx="41"> canv.style.left = x - 100 + <span class="tMagenta">'px'</span>;</cl-cd>
<cl-cd data-idx="42"> canv.style.top = y - 100 + <span class="tMagenta">'px'</span>;</cl-cd>
<cl-cd data-idx="43"> ctx.clearRect(0, 0, 200, 200);</cl-cd>
<cl-cd data-idx="44"> ctx.drawImage(img1, x - 25, y - 25, 50, 50, 0, 0, 200, 200);</cl-cd>
<cl-cd data-idx="45"> mTimer = setTimeout(<span class="tMagenta">'ctx.clearRect(0, 0, 200, 200)'</span>, 1000);</cl-cd>
<cl-cd data-idx="46">};</cl-cd>
<cl-cd data-idx="47"> </cl-cd>
<cl-cd data-idx="48"><<span class="tDarkRed">/script</span>></cl-cd>
<cl-cd data-idx="49"> </cl-cd>
<cl-cd data-idx="50"><<span class="tDarkRed">/body</span>></cl-cd>
<cl-cd data-idx="51"><<span class="tDarkRed">/html</span>></cl-cd>
</div>
一楼放大三倍,二楼的代码放大放大四倍。
二楼代码,CSS变量 --size 为 1,表示以 canvas 画布的实际尺寸即 200*200 渲染,画布则将图片鼠标指针所在的 50*50 区域方法,所以是 4 倍。画布以像素为单位操作图像,放大效果会失真。
一楼的实现机制和二楼的代码的实现机制不同,它有两个画布,一个显示图片,一个显示放大的图片区域。 路过,就点赞。 庶民 发表于 2024-4-10 17:35
路过,就点赞。
谢谢 可以放大很多呢,这个代码真神奇{:4_187:} 放大发丝,衣服上的花纹,还有眼睛鼻子等试了一下,蓝眼睛的最有冲击力{:4_170:} 把楼层二的图片地址输进去,一下子变很小了。原来楼层一的原始图片那么大{:4_173:} 这个标题有趣,还是包邮的放大镜{:4_173:} 换成《家乡的绿》的图片,试了一下。。
二者有点相通之处。。
南无月 发表于 2024-4-10 19:09
换成《家乡的绿》的图片,试了一下。。
二者有点相通之处。。
在效果上有形似之处,不过完全不是一个机制 红影 发表于 2024-4-10 19:05
这个标题有趣,还是包邮的放大镜
就是效果差一点哈 红影 发表于 2024-4-10 19:05
把楼层二的图片地址输进去,一下子变很小了。原来楼层一的原始图片那么大
有说明的,一楼的图片原始尺寸会压缩50% 南无月 发表于 2024-4-10 19:01
放大发丝,衣服上的花纹,还有眼睛鼻子等试了一下,蓝眼睛的最有冲击力
这个放大还是有点失真的 红影 发表于 2024-4-10 18:50
可以放大很多呢,这个代码真神奇
canvas画布的drawImage方法的功劳。可惜它基于像素,放大后多少失真 马黑黑 发表于 2024-4-10 19:10
在效果上有形似之处,不过完全不是一个机制
{:4_170:}
好哒,不同机制可以实现相似效果,这两个贴子一起投放还是挺好的呀 南无月 发表于 2024-4-10 19:15
好哒,不同机制可以实现相似效果,这两个贴子一起投放还是挺好的呀
好玩吧 马黑黑 发表于 2024-4-10 19:12
这个放大还是有点失真的
放大一般都会失真。。
无损放大PS好像不容易~~
代码放大同理。。应该也不容易 南无月 发表于 2024-4-10 19:16
放大一般都会失真。。
无损放大PS好像不容易~~
代码放大同理。。应该也不容易
svg可以 马黑黑 发表于 2024-4-10 19:15
好玩吧
前后脚放~~我是没想到机制完全不同。。。
能互动的效果都挺好玩的。。{:4_170:}