Canvas绘制图片合成样式

news/2024/12/21 20:50:32/文章来源:https://www.cnblogs.com/lisaShare/p/18404106

效果图
最终效果图

web

* {margin: 0;padding: 0;}.container {position: relative;width: 328px;height: 328px;margin: 100px auto;}.container img {position: absolute;width: 328px;height: 328px;}#canvas {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);z-index: 1;}.img-shape-bg {position: absolute;top: 0;left: 50%;width: 284px;height: 284px;transform: translateX(-50%) scale(1.4);opacity: .05;}
<div class="container"><img src="icosphere_red@2x.png" alt=""><canvas id="canvas" width="140" height="140"></canvas><!--  加一层背景模糊,优化背景色 --><view class="img-shape-bg" style="background-image: radial-gradient( circle, red 50%, transparent, transparent)"></view></div>
function mergeImages() {// 创建一个画布const canvas = document.getElementById("canvas");const context = canvas.getContext("2d");const overlay = new Image();// 蒙层及样版图片overlay.src = "mask@2x.png";overlay.onload = function () {context.drawImage(overlay, 0, 0, 140, 140);const template = new Image();template.src = "1.png";template.onload = function (res) {let width = height = 140let realWidth = template.widthlet realHeight = template.heightlet imgRatio = realWidth / realHeightlet sw = 0, sh = 0, sx = 0, sy = 0;let canvasRatio = width / height// 图片不变形if(imgRatio <= canvasRatio) {sw = realWidthsh = sw / canvasRatiosx = 0sy = (realHeight - sh) / 2} else { sh = realHeightsw = sh * canvasRatiosx = (realWidth - sw) / 2 sy = 0} // 仅在新形状和目标画布重叠的地方绘制新形状。其他的都是透明的context.globalCompositeOperation = "source-in";context.drawImage(template, sx, sy, sw, sh, 0, 0, 140, 140);};};}mergeImages()

miniprogram

.note-top-shape {box-sizing: border-box;position: relative;width: 284rpx;height: 284rpx;margin: auto;.img-shape-main {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -52%);width: 120rpx;height: 120rpx;z-index: 2;}.img-shape {position: relative;z-index: 1;}.img-shape-bg {position: absolute;top: 0;left: 50%;width: 284rpx;height: 284rpx;transform: translateX(-50%) scale(1.5);opacity: .05;}}
// 水晶<view class="note-top-shape"><image class="img-shape" src="{{ baseImageUrl }}{{ kindShape }}" mode="aspectFit" lazy-load="false" style="width: 284rpx;height: 284rpx;" binderror="" bindload="" />// canvas 在上面显示,因为canvas在小程序中层级太高,所以需要转化为image src展示<canvas type="2d" id="canvas_{{listItem.id}}" style="position: fixed;top: -9999px;left: -9999px;width: 240rpx;height: 240rpx;"></canvas><block><image class="img-shape-main" src="{{ imgPath }}" mode="aspectFit" lazy-load="false" binderror="" bindload=""></image></block>// 加一层背景模糊<view class="img-shape-bg" style="background-image: radial-gradient( ellipse at top, {{ listItem.style }} 50%, transparent, transparent)"></view></view>
Component({properties: {listItem: {type: Object,default: {//shape: 0,//style: red,}}},observers: {'listItem': function(item) {let shape = item.shapevar shapeImage = ''switch (shape) {case '0':shapeImage = 'pyramid'breakcase '1':shapeImage = 'cube'breakcase '2':shapeImage = 'diamond'breakcase '3':shapeImage = 'hexsphere'breakcase '4':shapeImage = 'icosphere'break}// 水晶图片是根据接口数据显示的let src = `shape/${shapeImage}_${item.style}@2x.png`this.setData({kindShape: src})}},data: {imgPath: ''},attached() {let item = this.data.listItemthis.mergeImagesMiniProgram(item.id, '/assets/images/mask@2x.png', item.photos[0])},methods: {mergeImagesMiniProgram(id, maskPath, filePath) {let that = thislet query = wx.createSelectorQuery().in(this)query.select(`#canvas_${id}`).fields({ node: true, size: true }).exec((rescanvas) => {let canvas = rescanvas[0].nodelet ctx = canvas.getContext('2d')const overlay = canvas.createImage()overlay.src = maskPathlet width = canvas.width = 120let height = canvas.height = 120let canvasRatio = width / heightoverlay.onload = function () {ctx.drawImage(overlay, 0, 0, width, height)const template = canvas.createImage()template.src = filePathtemplate.onload = function () {let realWidth = template.widthlet realHeight = template.height// coverlet imgRatio = realWidth / realHeightlet sw = 0, sh = 0, sx = 0, sy = 0;if(imgRatio <= canvasRatio) {sw = realWidthsh = sw / canvasRatiosx = 0sy = (realHeight - sh) / 2} else { sh = realHeightsw = sh * canvasRatiosx = (realWidth - sw) / 2 sy = 0} // ctx.globalCompositeOperation = "destination-in";ctx.globalCompositeOperation = "source-in";ctx.drawImage(template, sx, sy, sw, sh, 0, 0, width, height)// ctx.drawImage(template, 0, 0, width, height);wx.canvasToTempFilePath({canvas,width: width,height: height,destWidth: width * app.globalData.pixelRatio,destHeight: height * app.globalData.pixelRatio,success: async function(res) {let filePath = res.tempFilePath;that.setData({imgPath: filePath})},fail: function (res) {}})}}})}
})

素材图片

水晶

蒙层

我不叫胖虎

有需要可+qq:2091545890

参考文档-canvas drawImage绘图实现contain和cover的效果
参考文档-CanvasRenderingContext2D

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/794367.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Axure的画图规范说明

Axure的画图规范说明自定义网页整体尺寸:1366x768;色值:# F8F9FD 顶部一级导航:1366x48;色值:# 1D8FFF 左右布局,左侧边导航:768x194;色值:# 191A23 侧边导航栏宽高:194x768 左侧一级菜单宽高:194x40/边距:16,字号:14,色值:#FFFFFF,图标:14x14,二级导航宽194w,…

解决vscode终端输出中文乱码问题图文教程

由于系统终端默认编码为GBK,所以需要修改为UTF-8 方法一 打开cmd输入chcp查看编码格式,查看以及修改如下图所示:方法二

Transformer、RNN和SSM的相似性探究:揭示看似不相关的LLM架构之间的联系

通过探索看似不相关的大语言模型(LLM)架构之间的潜在联系,我们可能为促进不同模型间的思想交流和提高整体效率开辟新的途径。 尽管Mamba等线性循环神经网络(RNN)和状态空间模型(SSM)近来备受关注,Transformer架构仍然是LLM的主要支柱。这种格局可能即将发生变化:像Jamba、Samba…

【GeoEvent】实现点要素服务几何信息联合StreamServer流服务数据信息绑定

数据情况通过sid字段挂接,35个一组数据流结构 CSV ​​ IOT点位数据 ​​ 点位数据提前发布为FeatureServer要素服务注意关联字段类型与GeoEvent定义一致​​ ​​ 创建GeoEvent定义(数据结构)根据数据流结构决定,注意关联字段与GeoEvent定义一致​​ 创建TCP接收器 ​​ ​…

宝塔安装JDK

软件商店安装JDK后,设置一下JDK的版本: 拷贝一下JDK的路径:vim /etc/profile//追加内容 export JAVA_HOME=/www/server/java/jdk1.8.0_371 export JRE_HOME=${JAVA_HOME}/jre export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib export PATH=${JAVA_HOME}/bin:$PATH //保…

腾讯面试:说说6大Nginx负载均衡?手写一下权重轮询策略?

文章很长,且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录 博客园版 为您奉上珍贵的学习资源 : 免费赠送 :《尼恩Java面试宝典》 持续更新+ 史上最全 + 面试必备 2000页+ 面试必备 + 大厂必备 +涨薪必备 免费赠送 :《尼恩技术圣经+高并发系列PDF》 ,帮你 实现技术自由,…

ONCE论文阅读笔记

ONCE: Boosting Content-based Recommendation with Both Open- and Closed-source Large Language Models论文阅读笔记 Abstract ​ 现有的推荐器在理解项目内容方面面临着巨大挑战。大语言模型(LLM)拥有深层语义理解能力和来自预训练的广泛知识,已被证明在各种自然语言处理…

LeetCode刷题笔记9.2-9.9

leetCode刷题笔记(9.2-9.9) 48.旋转图像(9.3) 1)图像即二维数组,图像的旋转本质上是二维数组的旋转变换 2)二维数组从外层来看,是若干个子数组的集合,子数组内部维护各自的元素,即若干个row里是row.length个column 3)由此可理解下面几个关于二维数组的函数:创建二维数…

从零搭建 Docker 私有库

对于涉及机密的公司,不可能提供镜像给公网中的镜像仓库,所以需要创建一个本地私人仓库供给团队使用,基于公司内部项目构建镜像。对于涉及机密的公司,不可能提供镜像给公网中的镜像仓库,所以需要创建一个本地私人仓库供给团队使用,基于公司内部项目构建镜像。 Docker Regi…

[C++ Daily] 确保类复制了所有应该复制的成员

确保类复制了所有应该复制的成员结果:源代码: #include <iostream> #include <string> #include <vector> /*** copy操作应该包含对象内的所有成员变量及所有父类的成员变量,* 此种可以通过调用对应的拷贝构造与拷贝赋值操作完成*//// @brief simple termina…