前言
在网上冲浪的时候,发现一些小众的服饰网站能够对图片中模特的衣服进行换色,类似这样的(能明白就行,我可能录制的gif帧数太低)
这里来实现一下,最总效果是这样的
思路
比如要更改模特裙子的颜色
其实可以想象成有一个背景图是模特的全身,然后有一个和裙子形状重合的元素,更改其颜色即可
我能想到的解决方案有 :
- 使用clip-path画出一个裙子形状,对齐进行更改颜色
- 用canvas来画出裙子形状,更改颜色
- 使用蒙层mask来裁切出裙子的形状改变颜色
这里使用的第三种方式来实现,因为比较简单方便,不需要开发人员考虑裙子路径问题,只需要设计师做出对应的图片就可以
实现
素材
首先你需要两张图片,一张是模特的全身照,一张是和全身照尺寸一样,背景透明,只有裙子形状的地方是黑色的
这里我做了一个简单的图片用来代替模特和裙子图片(网上不知道去哪里找素材,哈哈)
模特全身照
写着'您'的白色方块代表模特的裙子位置
'您'字代表衣服褶皱
裙子图片
背景透明,黑色方块和上图的白色方块位置和尺寸一模一样,代表裙子
代码
第一步
先将结构写出来,搞一个div设置类名叫box吧,尺寸和模特全身照一致,背景设置为模特全身照
然后box中加一个div设置类名为replace,用来存放裙子图片,尺寸和box一致
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>换装功能</title>
</head>
<body>
<div class="box">
<div class="replace">
</div>
</div>
<style>
.box{
width: 500px;
height: 500px;
background: url('resource/1.png');
}
.replace{
width: 100%;
height: 100%;
background: url('resource/2.png');
}
</style>
</body>
</html>
效果
可以看到黑色方块正好和box中的白色方块重合
第二步
那么如何将黑色方块改为希望的颜色呢?
这里我们就要用到蒙层mask了
官方解释mask是这样的
CSS 属性 mask 允许使用者通过遮罩或者裁切特定区域的图片的方式来隐藏一个元素的部分或者全部可见区域。
该属性的全面解释可以参看 https://developer.mozilla.org/zh-CN/docs/Web/CSS/mask
这里不过多赘述,我们用的比较简单
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>换装功能</title>
</head>
<body>
<div class="box">
<div class="replace">
</div>
</div>
<button onclick="changecolor()">随机颜色</button>
<style>
.box{
width: 500px;
height: 500px;
background: url('resource/1.png');
}
.replace{
width: 100%;
height: 100%;
background-color: red;
mask: url('resource/2.png');
}
</style>
</body>
</html>
效果
解释
可以看到对应的位置颜色变为了代码中设置的background-color
mask的用法和background-image的用法一致,然后去掉background-image即可
现在我们初步实现了
但是还有一个问题,白色方块中'您'字却不见了,如果这是衣服的话,会造成衣服上的褶皱看不到
比如这样,就会显得衣服没有质感没有阴影变化
而应该是这种效果
那么应该怎么做呢
第三步
我们就需要用到混合模式了
mix-blend-mode
官方解释是
mix-blend-mode CSS 属性描述了元素的内容应该与元素的直系父元素的内容和元素的背景如何混合。
如果懂ps的同学应该能明白,这里需要正片叠加的方式
mix-blend-mode: multiply;
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>换装功能</title>
</head>
<body>
<div class="box">
<div class="replace">
</div>
</div>
<button onclick="changecolor()">随机颜色</button>
<style>
.box{
width: 500px;
height: 500px;
background: url('resource/1.png');
}
.replace{
width: 100%;
height: 100%;
background-color: red;
/* var(--replace-color); */
mask: url('resource/2.png');
mix-blend-mode: multiply;
}
</style>
</body>
</html>
效果
这样就达到了既能就该颜色,又能显示出非白色的地方
第四步
到第三步已经搞定了,不过为了更方便看效果,我们加上随机颜色和css变量
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>换装功能</title>
</head>
<body>
<div class="box">
<div class="replace">
</div>
</div>
<button onclick="changecolor()">随机颜色</button>
<style>
:root{
display: flex;
justify-content: center;
--replace-color: rgb(142, 190, 190);
}
.box{
width: 500px;
height: 500px;
background: url('resource/1.png');
}
.replace{
width: 100%;
height: 100%;
background-color: var(--replace-color);
mask: url('resource/2.png');
mix-blend-mode: multiply;
}
</style>
<script>
function changecolor(){
let randomColor = Math.random().toString(16).substring(2,8);
document.documentElement.style.setProperty('--replace-color','#'+randomColor)
}
</script>
</body>
</html>
解释
这里需要解释一下随机颜色,是利用随机数生成一个0-1之间的小数,然后转为16进制,截取从第三位开始的6位字符
然后修改css变量达到更改颜色的目的
总结
主要用到了
mask蒙层
mix-blend-mode混合模式
以及随机颜色,css变量等非必要内容