文档章节

使用canvas在前端添加水印

liyoungs
 liyoungs
发布于 01/20 11:22
字数 827
阅读 235
收藏 0
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <meta name="renderer" content="webkit">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <style>
    * {
      box-sizing: border-box;
      -moz-box-sizing: border-box;
      -webkit-box-sizing: border-box;
    }
    body,
    html {
      position: relative;
      width: 100%;
      height: 100vh;
      margin: 0;
      padding: 0;
      font: 12px/1.5 Tahoma, Verdana, Geneva, Arial, Helvetica, sans-serif;
    }
    input[type='text'] {
      width: 100%;
      height: 24px;
      /*-webkit-box-shadow: 0 1px 2px 0 rgba(34, 36, 38, 0.15);*/
      /*box-shadow: 0 1px 2px 0 rgba(34, 36, 38, 0.15);*/
      /*border-radius: 0.14285714rem;*/
      /*border: 1px solid rgba(34, 36, 38, 0.15);*/
    }
    .wrap {
      padding-top: 36px;
      width: 800px;
      margin: 0 auto;
      padding-bottom: 120px;
    }
    .wrap:after {
      content: " ";
      display: block;
      height: 0;
      clear: both;
      visibility: hidden;
    }
    .temp {
      float: right;
      width: 360px;
    }
    .diy {
      float: left;
      font-size: 0;
      position: relative;
    }
    .diy img {
      width: 360px;
      max-width: 100%;
    }
  </style>
</head>
<body>
<div class="wrap">
  <div class="temp">
    <input type="file" style="cursor: pointer;" id="file" onchange="createImg(this)" accept="image/*" />
    <div style="height: 10px;"></div>
    <input type="text" id="markTxt" value="请输入水印文字" />
    <div style="height: 10px;"></div>
    <label>字体大小:<input type="number" value="12" id="size"/></label>
    <div style="height: 10px;"></div>
    <label>
      字体样式:
      <select id="fStyle">
        <option selected value="normal">normal</option>
        <option value="italic">italic</option>
        <option value="oblique">oblique</option>
      </select>
    </label>
    <label>
      字体粗细:
      <select id="fWeight">
        <option value="100">100</option>
        <option value="200">200</option>
        <option value="300">300</option>
        <option selected value="400">400</option>
        <option value="500">500</option>
        <option value="600">600</option>
        <option value="700">700</option>
        <option value="800">800</option>
        <option value="900">900</option>
      </select>
    </label>
    <label>字体颜色:<input type="color" id="color"/></label>
    <div style="height: 10px;"></div>
    <button type="button" style="cursor: pointer;" onclick="createItem()">生成水印图片</button>
    <button type="button" style="cursor: pointer;margin-left: 36px;" onclick="dowload()">下载水印图片</button>
  </div>
  <div class="diy">
    <img src="images/pic.jpg" alt="" />
  </div>
</div>
<input type="hidden" id="cur" value="100,100" />
<script type="text/javascript">
  var flag = false;
  var flagImg = false;
  var imgData = null;
  function createItem() {
    var canvas = document.querySelector("#canvas");
    if (flag) {
      var markTxt = document.querySelector("#markTxt").value;
      var markSize = document.querySelector("#size").value;
      var markWeight = document.querySelector("#fWeight").value;
      var markStyle = document.querySelector("#fStyle").value;
      var color = document.querySelector("#color").value;
      var context = canvas.getContext("2d");
      if (flagImg) {
        imgData = context.getImageData(0, 0, canvas.width, canvas.height);
        flagImg = false;
      }
      context.clearRect(0, 0, canvas.width, canvas.height);
      context.putImageData(imgData, 0, 0, 0, 0, canvas.width, canvas.height);
      context.font = markStyle + " " + markWeight + " " + markSize + "px arial";
      context.fillStyle = color;
      // context.fillText(markTxt, canvas.width / 2, canvas.height - 12);
      var cur = document.querySelector("#cur").value;
      var mark = document.querySelector(".mark");
      if (mark) {
        mark.parentNode.removeChild(mark);
      }
      context.fillText(markTxt, cur.split(",")[0], cur.split(",")[1] + markSize);
    } else {
      alert("请上传图片");
    }
  }

  function createImg(et) {
    console.log(et);
    var file = et.files[0];
    var url = URL.createObjectURL(file);
    flag = true;
    flagImg = true;
    init(url);
  }
  function init(url) {
    var img = new Image();
    // 解决跨域 Canvas 污染问题
    // img.setAttribute("crossOrigin", "anonymous");
    img.onload = function() {
      var canvas = document.createElement("canvas");
      canvas.id = "canvas";
      if (flag) {
        canvas.style.cursor = "crosshair";
        canvas.setAttribute("onclick", "cnvs_getCoordinates()");
      }
      if (img.width >= 360) {
        canvas.width = 360;
        canvas.height = (img.height * 360) / img.width;
      } else {
        canvas.width = img.width;
        canvas.height = img.height;
      }
      console.log(canvas);
      var ctx = canvas.getContext("2d");
      ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
      if (url == "https://www.hnxaca.com/common/images/pic.jpg") {
        ctx.font = "italic bold 20px arial";
        ctx.fillStyle = "#f00";
        var cur = document.querySelector("#cur").value;
        ctx.fillText("这是一张水印图片", cur.split(",")[0], cur.split(",")[1]);
      }
      // ctx.drawImage(img, 0, 0);
      document.querySelector(".diy").innerHTML = "";
      document.querySelector(".diy").appendChild(canvas);
    };
    img.onerror = function(et) {
      throw new Error(et);
    };
    img.src = url;
  }
  init("https://www.hnxaca.com/common/images/pic.jpg");
  function dowload() {
    if (flag) {
      var canvas = document.querySelector("#canvas");
      var url = canvas.toDataURL(); //得到图片的base64编码数据
      var a = document.createElement("a"); // 生成一个a元素
      var event = new MouseEvent("click"); // 创建一个单击事件
      a.download = name || "photo"; // 设置图片名称
      a.href = url; // 将生成的URL设置为a.href属性
      a.dispatchEvent(event); // 触发a的单击事件
    } else {
      alert("请在图片上右击,选择'图片另存为'");
    }
  }
  function cnvs_getCoordinates(event) {
    var et = event || window.event;
    console.log(et.offsetX, et.offsetY);
    var x = et.offsetX;
    var y = et.offsetY;
    document.querySelector("#cur").value = x + "," + y;
    var markTxt = document.querySelector("#markTxt").value;
    var markSize = document.querySelector("#size").value;
    var markWeight = document.querySelector("#fWeight").value;
    var markStyle = document.querySelector("#fStyle").value;
    var color = document.querySelector("#color").value;

    var div = document.querySelector(".mark");
    if (!div) {
      div = document.createElement("div");
      div.setAttribute("class", "mark");
      div.style.position = "absolute";
    }
    // div.innerHTML = "Coordinates: (" + et.offsetX + "," + et.offsetY + ")";
    div.innerHTML = markTxt;

    // object.style.font="italic small-caps bold 12px arial,sans-serif"
    div.style.font = markStyle + " " + markWeight + " " + markSize + "px arial";
    div.style.color = color;

    div.style.left = et.offsetX + "px";
    div.style.top = et.offsetY + "px";

    if (!document.querySelector(".mark")) {
      document.querySelector(".diy").append(div);
    }
  }
</script>
</body>
</html>

 

© 著作权归作者所有

liyoungs

liyoungs

粉丝 1
博文 35
码字总数 7685
作品 0
郑州
前端工程师
私信 提问
加载中

评论(0)

使用canvas在前端实现图片合成

看着总结的不错,我也就拿来主义了,做个记录,侵权必删 图片合成最常见的需求有验证码图片,亦或者图片加水印等,这种实现一般都是后端实现的。 随着HTML5发展和现代浏览器的占比越来越高,...

xllily_11
2018/02/26
0
0
阿里云Aliplayer高级功能介绍(一):视频截图

摘要: H5 Video是不提供截图的API的, 视频截图需要借助Canvas,通过Canvas提供的drawImage方法,把Video的当前画面渲染到画布上, 最终通过toDataURL方法可以导出图片的base64编码,基本就...

阿里云云栖社区
2019/01/09
311
0
Node.js 服务端图片处理利器——sharp 进阶操作指南

Node.js 服务端图片处理利器——sharp 进阶操作指南 sharp 是 Node.js 平台上相当热门的一个图像处理库,其实际上是基于 C 语言编写 的 libvips 库封装而来,因此高性能也成了 sharp 的一大卖...

幸运券发放
2018/05/29
0
0
Node.js 服务端图片处理利器——Sharp 进阶操作指南

Sharp 是 Node.js 平台上相当热门的一个图像处理库,其实际上是基于 C 语言编写 的 libvips 库封装而来,因此高性能也成了 Sharp 的一大卖点。Sharp 可以方便地实现常见的图片编辑操作,如裁...

逆葵
2018/05/28
0
0
水印项目的实现以及两种实现方案的选优

水印项目我们提出了两种解决方案 一、用shadow dom实现 1、基本思路 通过 attachShadow 这个方法生成一个shadow root 即shadow的根节点,然后在这个根节点下面通过循环语句添加水印,利用pos...

粒子数反转
2019/06/20
25
0

没有更多内容

加载失败,请刷新页面

加载更多

2019 年 Google 编程之夏活动报告

本文首发于: Jenkins 中文社区 原文链接 作者:Martin d'Anjou,Jeff Pearce,Oleg Nenashev,Marky Jackson 译者:s1mple_zj 2019 年 Google 编程之夏活动报告 主要介绍了 GSoC 2019 活动的...

Jenkins中文社区
5分钟前
15
0
Spring Batch 在默认情况下的任务执行

在默认情况,如果你对 Spring Batch 不进行配置的话。 Spring Batch 将会对所有存在的作业(Job)进行执行。 考察项目:https://github.com/cwiki-us-spring/cwiki-us-spring-batch-examples...

honeymoose
今天
47
0
OSChina 周三乱弹 —— 提高不了工作效率和脸有关系

Osc乱弹歌单(2020)请戳(这里) 【今日歌曲】 @薛定谔的兄弟 :分享洛神有语创建的歌单「我喜欢的音乐」: 1 《夏令时记录(piano.ver)》- ゆめこ 手机党少年们想听歌,请使劲儿戳(这里) ...

小小编辑
今天
84
2
List的一波操作

public static void main(String[] args) { List<Entity> list = new ArrayList<>(); list.add(new Entity(1)); list.add(new Entity(2)); list.add(new Entity(3)); ......

那个猩猩很亮
今天
75
0
Spring基础

主要用于service层; 轻量级java开发框架; 各层 web层:struts,spring-MVC service层:spring dao层:hibernate,mybatis , jdbcTemplate --> spring-data Spring核心:控制反转IOC 切面编...

七宝1
今天
30
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部