zoukankan      html  css  js  c++  java
  • H5神器之canvas应用——网页修改保存图片

    因为最近项目上的要求,需要在页面中可以对一张图片进行涂改和添加文字,然后再保存到(服务器)本地,因为也是第一次接触这方面的,然后爬网页啊爬网页,之后发现了一款adobe开发的一款插件,适合 Anroid Ios 和Web的调用

    传送门 :感谢 翩翩 大神  http://www.cnblogs.com/hiflora/p/4267705.html

    发现这款插件非常的炫酷,功能也还是蛮强大的。但是万万没想到!!!当时也没有注意大神的使用说明:

    1,需要在线注册账号,申请apikey,地址:https://creativesdk.adobe.com/docs/web,这个apikey在代码调用时需要。这里也有详细的api文档,其他功能请参考文档说明,不过文档是英文的。

    2,要编辑的图片必须有固定的地址,可以被网络访问到。

    因为项目处理的图片我觉得应该不会有啥固定的地址吧,可以被网络访问到,我想更加不是现实的吧,到时候项目中保存的图片应该都是在本地的服务器上面,到时候有可能用的网络是在局域网用的,要访问这张图片应该是很难的吧,最后放弃了!!

    但是我觉得这个插件非常的炫酷,而且我觉得应该是蛮实用的,虽然点开页面反应时间有点长了点,但是人家功能叼啊。

    好了废话不多说了,进入主题。

    在扯几句,之后跟同事聊天的时候说起这件事,然后同事说可以用H5的canvas,突然灵光一闪,因为以前看过这个介绍、但是没有用过,觉得想想可行,于是就尝试这用canvas了。

    具体的canvas的他自带的属性我就不一一介绍了 传送门 http://www.w3school.com.cn/tags/html_ref_canvas.asp

    上代码HTML部分代码:

     1 <!DOCTYPE html>
     2 <html xmlns="http://www.w3.org/1999/xhtml">
     3 <head runat="server">
     4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
     5     <title>demo</title>
     6 </head>
     7 <body>
     8    <div>
     9        <canvas id="canvas" ></canvas>
    10        <img src="11.png" id="showPic" onclick="getPic()" >
    11    </div>
    12         <input type="text" name="fillWords" id="fillWords"> <button onclick="addWords()">文字添加</button>
    13         <button onclick="cleanPic()">清空</button>
    14         <button onclick="savePic()">保存</button>
    15 </body>
    16 </html>

    下面是js代码  感谢 http://www.oschina.net/code/snippet_221942_46198

     1 <script type="text/javascript">
     2     
     3       //全局变量
     4     var x_words, y_words;  //用于获得鼠标点击的坐标 用于插入文字
     5     var flag = false;
     6     var canvas, ctxl;
     7 
     8     canvas = document.getElementById('canvas');
     9     canvas.addEventListener('mousemove', onMouseMove, false);
    10     canvas.addEventListener('mousedown', onMouseDown, false);
    11     canvas.addEventListener('mouseup', onMouseUp, false);
    12 
    13     canvas.addEventListener('touchstart', onMouseDown, false);
    14     canvas.addEventListener('touchmove', onMouseMove, false);
    15     canvas.addEventListener('touchend', onMouseUp, false)
    16 
    17     canvas.height = 400;
    18     canvas.width = 600;
    19 
    20     ctx = canvas.getContext('2d');
    21     ctx.lineWidth = 3.0; // 设置线宽
    22     ctx.strokeStyle = "#CC0000"; // 设置线的颜色
    23 
    24     function onMouseMove(evt) {
    25         evt.preventDefault();
    26         if (flag) {
    27             var p = pos(evt);
    28             ctx.lineTo(p.x, p.y);
    29             x_words = p.x;
    30             y_words = p.y;
    31             ctx.lineWidth = 1.0; // 设置线宽
    32             ctx.shadowColor = "#CC0000";
    33             ctx.shadowBlur = 1;
    34             //ctx.shadowOffsetX = 6;
    35             ctx.stroke();
    36         }
    37     }
    38 
    39     function onMouseDown(evt) {
    40         evt.preventDefault();
    41         ctx.beginPath();
    42         var p = pos(evt);
    43         ctx.moveTo(p.x, p.y);
    44         flag = true;
    45     }
    46 
    47     function onMouseUp(evt) {
    48         evt.preventDefault();
    49         flag = false;
    50     }
    51 
    52     function cleanPic() {
    53         ctx.clearRect(0, 0, canvas.width, canvas.height);
    54     }
    55 
    56     function pos(event) {
    57         var x, y;
    58         if (isTouch(event)) {
    59             x = event.touches[0].pageX;
    60             y = event.touches[0].pageY;
    61         } else {
    62             x = event.layerX;
    63             y = event.layerY;
    64         }
    65         return {x: x, y: y};
    66     }
    67 
    68     function isTouch(event) {
    69         var type = event.type;
    70         if (type.indexOf('touch') >= 0) {
    71             return true;
    72         } else {
    73             return false;
    74         }
    75     }
    76 
    77     //添加文字
    78     function addWords() {
    79         var words = document.getElementById("fillWords").value;
    80         ctx.fillStyle = "#CC0000";
    81         ctx.font = "20px 微软雅黑";
    82         ctx.fillText(words, x_words, y_words);   // 文字
    83     }
    84 
    85     function savePic() {
    86         var pic  = document.getElementById('showPic');
    87         // 得到了需要保存的 相关图的信息 格式为:data:image/png;base64,xxxx" 有效的为xxxx部分
    88         var strDateUrl = canvas.toDataURL("image/png");  
    89            pic.src = strDateUrl;
    90     }
    91 
    92     function getPic() {
    93         var pic  = document.getElementById('showPic');
    94         // pic.crossOrigin = "anonymous";
    95         ctx.drawImage(pic, 0, 0, 600, 400);
    96     }
    97 </script>

    运行的效果图如下:

    本来,在这期间也遇到了一个问题: 因为我原本的打算是在 有背景的前提下面对于画面的更改,因为需求就是对图片的更改,之后保存么,所以目的是更改图片但是,当我点击图片的时候,虽然画布背景改变了,也可以添加文字和绘制一些乱七八糟的线条,但是在保存这图片的时候报了下面的错误:

    经过网上查询  发现是图片跨域的问题,这个名词 我以前都没听过 :(  这次又学习到了新知识   我查看的资料:传送门    感谢这位同学!

    但是,旧的问题解决了,新的问题又来了,当我为图片添加  crossOrigin = "anonymous"; 属性的时候,我在服务器上面是可有用的,也可以运行,但是把所以代码都提取出,就不可以运行了。就会报上面的错。

    下面顺便也把保存图片到本地 的方法写出来吧, 经过post提交之后,后台接受到提交过百的Base64值,转换成二进制之后,写到流文件中

     1 package com.sl.apps.acs.services.server;
     2 
     3 import com.cnblogs.yjmyzz.utils.FileUtil;
     4 import org.springframework.stereotype.Service;
     5 import sun.misc.BASE64Decoder;
     6 
     7 import java.io.File;
     8 import java.io.FileNotFoundException;
     9 import java.io.FileOutputStream;
    10 import java.io.IOException;
    11 
    12 /**
    13  * @author xueyuan
    14  * @dater 2016-11-9 0009.
    15  */
    16 @Service
    17 public class Base64ToImageService {
    18 
    19     public void Base64ToImageService(String imgStr) {
    20         String currentDir = FileUtil.currentWorkDir;
    21         String path = "images/1.jpg";
    22         saveImage(decode(imgStr.substring(22)),currentDir+path);
    23     }
    24 
    25 
    26     public static byte[] decode(String s) {
    27         BASE64Decoder decoder = new BASE64Decoder();
    28         byte[] bytes = null;
    29         try {
    30             bytes = decoder.decodeBuffer(s);
    31         } catch (IOException e) {
    32             e.printStackTrace();
    33         }
    34         return bytes;
    35     }
    36 
    37 
    38     public void saveImage(byte[] imageBytes,String path){
    39         File file=new File(path);
    40         FileOutputStream outputStream=null;
    41         try {
    42             outputStream=new FileOutputStream(file);
    43             outputStream.write(imageBytes);
    44         } catch (FileNotFoundException e) {
    45             e.printStackTrace();
    46         } catch (IOException e) {
    47             e.printStackTrace();
    48         } finally{
    49             closeSteam(outputStream);
    50         }
    51     }
    52 
    53     public void closeSteam(FileOutputStream outputStream){
    54         if(outputStream!=null){
    55             try {
    56                 outputStream.close();
    57             } catch (IOException e) {
    58                 e.printStackTrace();
    59             }
    60         }
    61     }
    62 
    63 }

    在解决保存的时候又发现了新的问题,因为我用的是jetty为容器的,没有设置maxFormContentSize 这个属性,因为post的不能超过2M的数据,所以要把这个属性设置为你需要的大小 或者为-1,即不限制大小:

    感谢这位同学: jetty修改限制上传大小 

    以上就是这次记录的全部内容,如有不足,请指教!

  • 相关阅读:
    hdfs java.io.IOException: Mkdirs failed to create
    Linux文件权限授予
    插入排序
    Oracle中怎样设置表中的主键id递增
    单链表中是否有环之java实现
    excel 单元格的锁定 以及 JXL的实现方式
    用POI的HSSF来控制EXCEL的研究
    Oracle Job 语法和时间间隔的设定(转)
    您的JAVA代码安全吗?(转)
    Jdom 解析 XML【转】
  • 原文地址:https://www.cnblogs.com/eoooxy/p/6051343.html
Copyright © 2011-2022 走看看