• uniapp图片加水印


    1、uniapp加水印

    1.1、创建画布容器

    1. <canvas class="watermark-canvas" id="watermark-canvas" canvas-id="watermark-canvas"
    2. :style="{ width: canvasWidth, height: canvasHeight }" />

    1.2、获取水印内容

    1. famartWeek(e) {
    2. switch (e) {
    3. case 0:
    4. return '日'
    5. case 1:
    6. return '一'
    7. case 2:
    8. return '二'
    9. case 3:
    10. return '三'
    11. case 4:
    12. return '四'
    13. case 5:
    14. return '五'
    15. case 6:
    16. return '六'
    17. }
    18. },
    19. async getLocation() {
    20. const zero = (item) => item < 10 ? "0" + item : item
    21. const time = new Date();
    22. const yy = time.getFullYear();
    23. const mm = time.getMonth() + 1;
    24. const dd = time.getDate();
    25. const hh = time.getHours();
    26. const MM = time.getMinutes();
    27. const ww = this.famartWeek(time.getDay())
    28. const hm = zero(hh) + ':' + zero(MM)
    29. const ymd = yy + '-' + zero(mm) + '-' + zero(dd) + ' 星期' + ww
    30. const {
    31. name: location
    32. } = await this.$store.dispatch('location/juGetLocation')
    33. return {
    34. hm,
    35. ymd,
    36. address: location
    37. }
    38. },

    1.3、添加水印上传图片

    1. async chooseImage(e) {
    2. uni.chooseImage({
    3. sourceType: sourceType[this.sourceTypeIndex],
    4. sizeType: ['compressed'],
    5. count: this.limit,
    6. success: async (res) => {
    7. let filePath = res.tempFilePaths[0]
    8. const watermark = await this.getLocation()
    9. //压缩图片设置宽度,不然画不全
    10. uni.compressImage({
    11. src: filePath,
    12. quality: 80,
    13. compressedHeight: 1200,
    14. success: async comres => {
    15. //绘制图片加水印
    16. let img = await this.fillTextToImg(comres.tempFilePath, watermark)
    17. uni.showLoading({
    18. title: '上传中...',
    19. mask: true
    20. })
    21. const arr = [img]
    22. // 上传图片
    23. const key = await this.$store.dispatch('upload/uploadFileList', arr)
    24. this.$emit('handleChangeKeys', {
    25. src: key,
    26. create_time: watermark.hm,
    27. sign_date: watermark.ymd,
    28. sign_local: watermark.address
    29. })
    30. uni.hideLoading()
    31. }
    32. })
    33. },
    34. fail: (err) => {}
    35. })
    36. },
    37. sleep(millisecond) {
    38. return new Promise((resolve) => {
    39. setTimeout(resolve, millisecond)
    40. })
    41. },
    42. fillTextToImg(file, watermark) {
    43. return new Promise((resolve, reject) => {
    44. uni.getImageInfo({
    45. src: file,
    46. success: async res => {
    47. //设置画布大小,然后再画,不然会只画一部分
    48. this.canvasWidth = `${res.width}px`
    49. this.canvasHeight = `${res.height}px`
    50. console.log(res.width, res.height);
    51. const bol = res.width < res.height
    52. let waterW = res.width
    53. if (bol && waterW < 650) {
    54. waterW = 650
    55. }
    56. if (bol && waterW > 800) {
    57. waterW = 800
    58. }
    59. if (!bol) {
    60. waterW = 800
    61. }
    62. await this.sleep(200)
    63. const ctx = uni.createCanvasContext('watermark-canvas', this)
    64. ctx.clearRect(0, 0, res.width, res.height)
    65. ctx.beginPath()
    66. ctx.drawImage(res.path, 0, 0, res.width, res.height)
    67. // 水印 字体大小,颜色,内容,位置
    68. ctx.beginPath()
    69. ctx.font = 'bold 24px 黑体'
    70. // 背景
    71. let fw = waterW / 12
    72. ctx.fillStyle = "rgb(24,177,237)";
    73. ctx.fillRect(10, res.height / 4 * 2.8, fw * 4.2, fw * 1.4);
    74. ctx.textBaseline = 'top'
    75. ctx.setFillStyle('#ffffff')
    76. ctx.setFontSize(fw)
    77. ctx.fillText('家宴打卡', 10, res.height / 4 * 2.8 + 10)
    78. // 背景
    79. ctx.fillStyle = "#ffffff";
    80. ctx.fillRect(10, res.height / 4 * 2.8 + fw * 1.4, fw * 4.2, fw * 1.4);
    81. ctx.setFillStyle('rgb(31,53,93)')
    82. ctx.setFontSize(waterW / 9)
    83. ctx.fillText(watermark.hm, 10, res.height / 4 * 2.8 + fw * 1.4)
    84. ctx.setFillStyle('#ffffff')
    85. ctx.setFontSize(waterW / 14)
    86. ctx.fillText(watermark.ymd, 10, res.height / 4 * 2.8 + fw * 1.4 * 2.2)
    87. ctx.setFontSize(waterW / 16)
    88. ctx.fillText(watermark.address, 10, res.height / 4 * 2.8 + fw * 1.4 * 3)
    89. // 开始绘制 (canvas -> 临时文件路径)
    90. ctx.draw(false, async () => {
    91. await this.sleep(500) // 某些平台 canvas 渲染慢,需要等待
    92. uni.canvasToTempFilePath({
    93. canvasId: 'watermark-canvas',
    94. destWidth: res.width,
    95. destHeight: res.height,
    96. fileType: 'jpg',
    97. quality: 0.8,
    98. success: (fileRes) => {
    99. resolve(fileRes.tempFilePath)
    100. },
    101. fail: (err) => {
    102. uni.showToast({
    103. title: err.errMsg,
    104. icon: 'none'
    105. })
    106. reject()
    107. },
    108. },
    109. this,
    110. )
    111. })
    112. },
    113. fail: (err) => {
    114. console.log('[Error getImageInfo]', err)
    115. uni.showToast({
    116. title: err.errMsg,
    117. icon: 'none'
    118. })
    119. reject()
    120. },
    121. })
    122. });
    123. },

    1.4、设置画布位置,不让其显示

    1. .watermark-canvas {
    2. transform: scale(1);
    3. transform-origin: 0 0;
    4. position: absolute;
    5. top: -999px;
    6. left: -999px;
    7. }

    ps:效果图

    2、web端加水印(Image,FileReaderweb端才能使用)

    1. // 获取本地图片的base64编码
    2. // 使用在线图片链接的时候需要注意给图片设置crossOrigin属性
    3. function fileToBase64Async(file) {
    4. return new Promise((resolve, reject) => {
    5. let reader = new FileReader();
    6. reader.readAsDataURL(file);
    7. reader.onload = (e) => {
    8. resolve(e.target.result);
    9. };
    10. });
    11. }
    12. // fillText绘制的是默认的普通实线文本,strokeText绘制的是描边文本
    13. function fillTextToImg(base64) {
    14. const img = new Image();
    15. img.src = base64;
    16. img.setAttribute("crossOrigin", "Anonymous");
    17. return new Promise((resolve, reject) => {
    18. img.onload = () => {
    19. // 生成一个 canvas 画布;
    20. const canvas = document.createElement("canvas");
    21. canvas.width = img.width;
    22. canvas.height = img.height;
    23. // 将现有需要添加水印的图片绘制到画布上;
    24. const ctx = canvas.getContext("2d");
    25. ctx.fillRect(0, 0, canvas.width, canvas.height);
    26. ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
    27. const remFontSize = canvas.width / 35;
    28. ctx.font = "bolder " + remFontSize + "px Verdana";
    29. ctx.textAlign = "center";
    30. /**
    31. ctx.textAlign = "center|end|left|right|start";
    32. start:默认,文本在指定的位置开始。
    33. end:文本在指定的位置结束。
    34. center:文本的中心在指定的位置。
    35. left:文本左对齐。
    36. right:文本右对齐。
    37. **/
    38. ctx.strokeStyle = "#fff";
    39. const name = "@AAAAAAAAAAAAA";
    40. const spaceH = remFontSize * 0.3;
    41. ctx.fillText(
    42. name,
    43. canvas.width / 2,
    44. canvas.height - remFontSize - spaceH
    45. );
    46. resolve(canvas.toDataURL("image/jpeg"));
    47. };
    48. });
    49. }

  • 相关阅读:
    移植 simpleFoc笔记(一)
    私域2.0时代,如何搭建「有魔力」的小程序积分商城?
    JS-内置对象API-Array(数组)-(二)不改变原数组的API-篇
    Qt ARM+Linux平台调用一个库的时候,报错“Bus error”
    nginx基础架构
    win10任务栏出现无法删除的空白块
    c++刷题常用stl用法
    解决问题:请使用golang编写代码实现一个简易的区块链,包含如何创建区块、如何加密哈希、如何链接区块等功能?
    Android lint配置及使用
    14、三维表面重建-DeepSDF
  • 原文地址:https://blog.csdn.net/weixin_48046344/article/details/133921615