Please enable Javascript to view the contents

写了个莱卡水印生成器,小米不会告我吧?

 ·  ☕ 3 分钟

引子

好久没关注手机,最近听了雷布斯的演讲【全程回放】2022雷军年度演讲 - 西瓜视频,才发现小米跟莱卡达成战略合作,出了款Xiaomi 12S Ultra小米莱卡镜头手机。

先不说小米莱卡拍照如何,单看照片下面的可乐标水印,德味感扑面而来。网友纷纷表示“毒”啊,于是就有网友制作了小米水印生成器

小米水印生成器

小米水印生成器 - V2EX

这个生成器非常好用,但也发现几个小问题:

  1. 没有使用小米字体
  2. 不能读取原照片文件名
  3. 不能读取照片拍摄时间、修改时间
  4. 修改了原来的照片尺寸,下载图片尺寸固定

于是我就在这个网页的UI基础上加上了以上几个功能。

莱卡水印生成器

莱卡水印生成器 by 码中人

实现原理

以前写过一个代码截图小工具,是通过 html2canvas 把 html 元素渲染成图片下载下来。
这次原理类似,就是在图片下面排版好leica水印信息,再通过 html2canvas 将图片与水印信息的容器元素渲染成图片。

全部为前端技术,包括:

  • html2canvas
  • react
  • tailwind csss。

CodeImg 代码截图 by 码中人
so easy…自制代码截图工具 – 码中人的博客

具体实现

初始化项目

通过 tailwind css 实现UI

UI

导入小米字体

MIUI 13 采用全新系统字体 MiSans。笔型平直有力,设计更加简约,减少视觉负担,更有利于屏幕显示。共包含29,093个字符,支持多种语言。MiSans 提供了多种 OpenType 功能,可根据特定需求来选择不同形态的字符,例如某些标点符号可以根据周围字母的形态自动调整至合适的位置。MiSans字重齐全,层级清晰,10个字重全部开放下载,供全社会免费商用。

下载链接:MiSans字体下载

1
2
3
4
5
6
7
8
9
@font-face {
  font-family: "MiSans";
  font-weight: 400;
  src: url("./fonts/MiSans-Normal.ttf");
}

body{
  font-family: MiSans;
}

通过 FileReader 读取本地照片

通过<input type="file">接收图片文件。

1
<input type="file" accept="image/*" className="hidden" id='select-image' onChange={handleFileChange}></input>

选择图片文件后,触发input onchange 事件,调用FileReader读取文件内容。

1
2
3
4
5
6
7
8
const handleFileChange = (e) => {
    const file = e.target.files[0];
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = (e) => {
        setImgSrc(e.target.result)
    }
}

FileReader.readAsDataURL() - Web API 接口参考 | MDN

readAsDataURL 方法会读取指定的 Blob 或 File 对象。读取操作完成的时候,readyState 会变成已完成DONE,并触发 loadend (en-US) 事件,同时 result 属性将包含一个data:URL 格式的字符串(base64 编码)以表示所读取文件的内容。

最后 setImgSrc(e.target.result)将图片内容加载显示出来。

读取上传图片名称和最后修改时间,全局保存

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
+ const {setImageName,setImageDate} = useContext(ImageContext);
const handleFileChange = (e) => {
    const file = e.target.files[0];
+   setImageName(file.name);
+   setImageDate(file.lastModifiedDate);
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = (e) => {
        setImgSrc(e.target.result)
    }
}

点击下载图片

读取图片的 naturalWidth 与图片的显示宽度相比较,得到缩小比例值。生成图片宽度时放大该比例,这样图片大小就跟原来一样。

HTMLImageElement.naturalWidth - Web APIs | MDN

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
const downloadImage = (selector, name = "莱卡水印-by-码中人.png") => {
    const img = $('#selected-image');
    const width = img.width;
    const naturalWidth = img.naturalWidth;
    const scale = naturalWidth / width;
    const el = document.querySelector(selector);
    html2canvas(el, { // 转换为图片
        useCORS: true, // 解决资源跨域问题
        scale: scale, // 设置图片放大倍数
    }).then(canvas => {
        let imgUrl = canvas.toDataURL('image/png');
        mockDownload(imgUrl, name)
    })
}

模拟下载即可。

1
2
3
4
5
6
const mockDownload = (imgsrc, name) => {
    const aLink = document.createElement('a');
    aLink.download = name;
    aLink.href = imgsrc;
    aLink.click();
}

下一步内容

PC端正常好用。手机端的水印排版有问题,input 内文字显示不全。哪位大神帮小弟修复一下。

小米字体MiSans 特别的大,第一次加载非常慢,有待进一步优化。

视频演示

小米莱卡水印生成器_哔哩哔哩_bilibili

代码下载

mzhren/xiaomi-leica

分享

码中人
作者
码中人
Web Developer