html5 canvas 在线图片转换器

前天写完文件上传的时候,老板给了个任务,问我能不能把图片压缩后再上传,并且保证前面的功能能正常使用。虽然最后放弃了这个想法,但我在查资料的过程中看到了canvas的toDataURL这个功能。于是就想能不能做一个在线的图片转换器。在经过一天的辛苦耕耘后(我是不会告诉你们我在事件绑定上浪费了半天时间( ´艸`)ムププ),总算弄出个大概了。虽然还有一些东西不太明白,但总体没什么问题了。
主要的几个功能就是:
1.toDataURL(用来压缩转码)
2.通过后台的临时储存来达到跨域获取图片(虽然html5提供了跨域获取图片的方式,但这要你情我愿才行啊(´・ω・`) )
3.js下载图片

有关html5图片跨域可以参考这篇文章:https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image

感谢下面的文章提供的学习方向:
http://www.baidufe.com/item/65c055482d26ec59e27e.html
http://blog.csdn.net/chaojie2009/article/details/22047871

演示地址:我是demo
源码地址:点我下载

首先
HTML:

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>IMGFormat</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
<link rel="stylesheet" type="text/css" href="css/format.css">
</head>
<body>
<header id="header">IMGFormat</header>
<section id="content">
    <section id="con_box">
        <div class="img_box"><img src="img/1.jpg" id="source_img"></div>
        <canvas id="canvas"></canvas>
        <div class="to">TO</div>
        <div class="img_box"><img src="img/1.jpg" id="preview_img"></div>
        <div class="select_box">
            <select id="way_choose">
                <option selected="selected">本地文件选择</option>
                <option>网络文件选择</option>
            </select>

            <section class="file_choose">
                <span>请选择image文件:</span>
                <label for="file">+</label>
                <input type="file" id="file" name="file" accpet="image/*">
            </section>
            <section class="url_input">
                <label for="urlGet">请输入图片链接:</label>
                <input type="text" id="urlGet" name="urlGet" placeholder="如:http://www.xx.com/1.jpg">
            </section>
        </div>
        <div class="tips t1">
            使用链接时请注意图片是否是外链。目前仅支持:jpg|png|gif|bmp
        </div>
        <div class="tips t2">
            当图片较大时,转png格式可能失败(作者表示他不知道原因Σ(゚д゚lll))。
            如果有谁知道的话,欢迎在文章下面的评论留言,谢谢。
        </div>
    </section>
</section>
<footer id="footer">
    <span>转换格式选择:</span>
    <ul class="type_list">
        <li class="bgAdd">JPG</li>
        <li>PNG</li>
    </ul>
    <label for="quality">图片质量:</label>
    <input id="quality" name="quality" type="number" min="10" max="100" step="10" value="50">
    <button id="turnTo">转换</button>
    <button id="download">下载</button>
</footer>
<a id="downIMG"></a>
<script type="text/javascript" src="js/format.js"></script>
</body>
</html>

CSS:

style.css

/*************reset****************/
html{color:#333;-webkit-text-size-adjust:none;height:100%;max-height:100%;overflow: hidden;font-family: 'Microsoft Yahei';}
body{height: 100%;max-height:100%;overflow: hidden;}
body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td{margin:0;padding:0;}
table{border-collapse:collapse;border-spacing:0;}
fieldset,img{border:0;}
address,caption,cite,code,dfn,em,var,optgroup{font-style:inherit;font-weight:inherit;}
del,ins{text-decoration:none;}
li{list-style:none;}
h1,h2,h3,h4,h5,h6{font-size:100%;}q:before,q:after{content:'';}
abbr,acronym{border:0;font-variant:normal;}
sup{vertical-align:baseline;}
sub{vertical-align:baseline;}legend{color:#000;}
input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;}input,button,textarea,select{*font-size:100%;}
body{font-size:12px;}
a{color: #333333;text-decoration: none;}
a:hover{text-decoration:underline; color:#c00;}

/*font*/
*{
    font-size: 1.05em;
    color: #222;
    font-family: "Microsoft Yahei";
}

format.css

body{
    background: -webkit-linear-gradient(#66ccff,#74b1d1);
    background: -o-linear-gradient(#66ccff,#74b1d1);
    background: -moz-linear-gradient(#66ccff,#74b1d1);
    background: -ms-linear-gradient(#66ccff,#74b1d1);
    background: linear-gradient(#66ccff,#74b1d1);
    position: relative;
}
#header{
    height: 2.8em;
    background: -webkit-linear-gradient(rgba(34,34,34,0.9),rgba(0,0,0,0.7));
    background: -o-linear-gradient(rgba(34,34,34,0.9),rgba(0,0,0,0.7));
    background: -moz-linear-gradient(rgba(34,34,34,0.9),rgba(0,0,0,0.7));
    background: -ms-linear-gradient(rgba(34,34,34,0.9),rgba(0,0,0,0.7));
    background: linear-gradient(rgba(34,34,34,0.9),rgba(0,0,0,0.7));
    font-size:2.4em;
    font-weight: bolder;
    text-align: center;
    line-height: 2.8em;
    color: #fff;
    text-shadow:0 0 0 #eee,0 0 0 #eee,1px 1px 1px #ede,-1px -1px 1px #eee;
    box-shadow: 0px 2px 6px rgba(16,16,16,0.7);
}

#content{
    position: absolute;
    top: 10em;
    left: 0em;
    bottom: 8em;
    right: 0em;
    padding: 0em 2em;
}

#con_box{
    height: 100%;
    background: #fff;
    box-shadow:0px 0px 10px rgba(0,0,0,0.9);
    border: none;
    border-radius: 10px;
    padding:0em 8%;
    position: relative;
    text-align: center;
}

.img_box{
    width: 100%;
    max-width: 36%;
    max-height: 63.4%;
    height: 100%;
    display: inline-block;
    margin-top: 2em;
    position: relative;
}

.img_box img{
    max-width: 100%;
    max-height: 100%;
    width: 100%;
    height: 100%;
    vertical-align: middle;
}

#canvas{
    display: none;
}

.to{
    display: inline-block;
    width: 20%;
    max-width: 20%;
    font-size: 3em;
    font-weight: bolder;
}

.select_box{
    text-align: left;
    width: 92%;
    margin:0 auto;
    margin-top: 2em;
}

#way_choose{
    float: left;
    margin-right: 2em;
}

.file_choose,.url_input{
    margin: 0 auto;
    font-weight: bold;
    font-size:1.4em;
    text-align: left;
    display: none;
}

.file_choose{
    display: block;
}

.file_choose>label{
    margin-left: 2em;
    padding:0 1.2em;
    font-size: 1.1em;
    font-weight: bolder;
    background: #222;
    color:#fff;
}

.file_choose>label:hover{
    cursor: pointer;
    box-shadow: 0 0 5px red;
}

.file_choose>input{
    display: none;
}

.url_input>label{
    margin-right: 1em;
}

.url_input>input{
    outline: none;
    border: 2px solid #dedede;
    border-radius: 2em;
    padding-left: 1.5em;
    width:20em; 
}

.tips{
    text-align: left;
    font-size: 1.2em;
    font-weight: bold;
    width: 92%;
    margin:0 auto;
    margin-top: 1em;
    display: none;
}

.t1{
    display: block;
}

#footer{
    position: fixed;
    bottom: 0em;
    height: 2.8em;
    background: #000;
    line-height: 2.8em;
    width: 100%;
    left: 0em;
    font-size: 1.6em;
    font-weight: bolder;
}

#footer>span{
    float: left;
    margin-left:1.5em;
}

.type_list{
    display: inline;
    margin-right: 2em;
}

.type_list>li{
    display: inline;
    margin-left: 1em;
    background: #ffb515;
    height: 2em;
    padding:0 0.6em;
    font-size: 1.05em;
    color: #fff;
    text-shadow:-1px 1px 2px rgba(0,0,0,0.7);
    border-radius:5px;
    box-shadow:0 0 5px rgba(255,255,255,0.6);
}

.type_list>li:hover{
    cursor: pointer;
    box-shadow: 0 0 5px rgba(255,0,0,0.7);
}

#quality{
    margin-left: 1em;
}

#turnTo,#download{
    margin-left: 2em;
    padding: 0 1em;
    border-radius: 10px;
    border: 1px solid #d9d9d9;
    background: -webkit-linear-gradient(#ffffff,#dfdfdf);
    background: -o-linear-gradient(#ffffff,#dfdfdf);
    background: -moz-linear-gradient(#ffffff,#dfdfdf);
    background: linear-gradient(#ffffff,#dfdfdf);
    box-shadow: 0px 0px 5px rgba(255,255,255,0.7);
    font-weight: bolder;
}

#turnTo:hover,#download:hover{
    background: -webkit-linear-gradient(#66ccff,#74b1d1);
    background: -o-linear-gradient(#66ccff,#74b1d1);
    background: -moz-linear-gradient(#66ccff,#74b1d1);
    background: -ms-linear-gradient(#66ccff,#74b1d1);
    background: linear-gradient(#66ccff,#74b1d1);
    cursor: pointer;
    border: #6cf 1px solid;
}

.bgAdd{
    background: red !important;
}

JS:

//author:孤月
//date:2015/07/17
//变量定义
var sWay    = document.getElementById("way_choose"),       //获取得到图片链接的方式
    sGetUrl = "",                                          //当获取方式为链接时,存放获取的链接地址
    sFile   = "",                                          //当获取方式为本地时,存放获取的文件信息
    sType   = "",                                          //获取要转换的格式
    nQuali  = document.getElementById("quality");           //获取图片转换的质量(压缩比)

var urlInput  = document.getElementById("urlGet"),
    file      = document.getElementById("file"),
    sourceImg = document.getElementById("source_img"),
    previewImg= document.getElementById("preview_img"),
    canvas    = document.getElementById("canvas"),
    typeList  = document.querySelector(".type_list"),
    turnTo    = document.getElementById("turnTo"),
    download  = document.getElementById("download");

var mimeTypeGet,        //获取img格式
    canDownload=false,  //是否可以开始下载
    cross,              //是否是外链
    go=true;            //是否文件或链接或转换格式改变


//获取要转换的目标图片类型
function getType () {
    var type;
    //侦听click事件
    typeList.addEventListener("click",function(e){
        e = e || event;
        if(e.target.tagName.toLowerCase()!="li")
        return;
        var val = e.target.innerHTML;
        var ch = typeList.children;

        for(var x=0;x<ch.length;x++)
        ch[x].setAttribute("class","");
        e.target.setAttribute("class","bgAdd");

        //当目标类型改变时,允许转换
        if(sType!=val.toLowerCase)
        go = true;

        sType = val.toLowerCase();
        if(sType=="jpg")
        {
            document.getElementById("quality").style.display="inline-block";
            document.querySelector(".t2").style.display="none";
            document.querySelector(".t1").style.display="block";
        }
        else{
            document.getElementById("quality").style.display="none";
            document.querySelector(".t1").style.display="none";
            document.querySelector(".t2").style.display="block";
        }
    },false);
}

//获取图片取得方式
function wayChange(){
    //侦听change事件
    sWay.addEventListener("change",function(){
        var fc = document.querySelector(".file_choose"),
            ui = document.querySelector(".url_input");
        (sWay.value=="本地文件选择")?FileShow():UrlShow();
        function FileShow(){
            fc.style.display = "block";
            ui.style.display = "none";
            cross = false;
        };

        function UrlShow(){
            fc.style.display = "none";
            ui.style.display = "block";
            cross = true;
        }

        turnTo.style.display = "none";
        download.style.display="none";
        file.value = "";
        urlGet.value = "";
    },false);
}

//当文件域变化
function fileChange(){
    file.addEventListener("change",function(){

        //读取文件
        var files = file.files[0];
        var reader = new FileReader();
        reader.onload = function(e){
            go = true;
            e = e || event;
            sourceImg.src = e.target.result;
            turnTo.style.display = "inline-block";
            download.style.display="inline-block";
            transformImg();
        };
        reader.readAsDataURL(files);
    },false);
}

//当地址输入完毕
function urlInputEnd(){
    var match;
    urlInput.addEventListener("blur",function(){
        //匹配链接
        if(!urlInput.value)
        return;
        match = /.jpg|.png|.gif|.bmp/;
        sGetUrl = urlGet.value;
        var temp = sGetUrl.substring(sGetUrl.lastIndexOf("."));
        if(match.test(temp))
        {
            sourceImg.src = sGetUrl;
            sourceImg.onload = function(){
                go = true;
                turnTo.style.display = "inline-block";
                download.style.display="inline-block";
                transformImg();
            };
        }
    },false)
}

//压缩比变化时
function qualityChange(){
    nQuali.onchange = function(e){
        //限制取值
        var val = e.target.value.toFixed(0);
        if(!val || val>100 || val<10)
        nQuali.value = 50;
    };
}

//img下载
function downlo(){
    download.onclick = function(){
        if(canDownload)
        {  
            // 加工image data,替换mime type
            var imgData = previewImg.src.replace(mimeTypeGet,'image/octet-stream');
            //download
            var down = document.getElementById("downIMG");
            down.href = imgData;
            down.download = "IGotIt-"+(new Date()).getTime()+"."+(sType?sType:"jpg");
            var mouseEv = document.createEvent("MouseEvents");
            mouseEv.initMouseEvent("click",false,false,window,0,0,0,0,0,false,false,false,false,0,null);
            down.dispatchEvent(mouseEv);
        } else {
            alert("请先进行转换!");
        }
    };
}

//转换
function transformImg(){
    turnTo.onclick = function(e){
        e = e || event;
        e.stopPropagation();
        e.preventDefault();
        var type = sType || "jpg" ,
            mimeType,
            newImage = new Image(),
            cv = canvas,
            ct = cv.getContext('2d');

        if(type=="jpg")
        mimeType = "image/jpeg";
        else
        mimeType = "image/"+type;

        mimeTypeGet  = mimeType;

        if(cross && go){
            //获取外链地址并将其传入服务器
            var xhr = new XMLHttpRequest();
            var nForm = new FormData();

            nForm.append("url",sourceImg.src);
            nForm.append("type",sourceImg.src.substring(sourceImg.src.lastIndexOf('.')));

            xhr.open('POST','php/send.php');
            xhr.send(nForm);

            xhr.addEventListener("load",function(e){
                go = false;
                var newSrc = e.target.responseText;
                newImage.src = newSrc;
                newImage.onload = function(){
                    previewImg.src=trans().src;
                    nForm.append("del",true);
                    xhr.open("POST",'php/del.php');
                    xhr.send(nForm);
                };
            },false);
        } else if(go){
            newImage.src = sourceImg.src;
            previewImg.src=trans().src;
        }

        function trans(){
            cv.width = newImage.width;
            cv.height= newImage.height;
            ct.drawImage(newImage,0,0);
            if(mimeType=="image/jpeg")
            var newData = cv.toDataURL(mimeType,nQuali.value/100);
            else
            var newData = cv.toDataURL(mimeType); 
            var nImage = new Image();
            nImage.src = newData;
            canDownload = true;
            downlo();
            return nImage;
        }
    };
}

function init(){
    getType();
    wayChange();
    fileChange();
    urlInputEnd();
    qualityChange();
}

init();

PHP:

send.php

<?php
session_start();
if(!$_POST)
return false;
$dataUrl = trim(mb_convert_encoding($_POST['url'],'gbk','utf-8'));
$type = $_POST['type'];

$path = "../";
$random = time().rand(1,10000);
$dir  = "source/".$random."/";
$name = rand(10000,20000).$type;

if(!is_dir($path.$dir))
{
    mkdir($path.$dir);
    chmod($path.$dir,0777);
}

$newImageData = @file_get_contents($dataUrl);

$createImg = fopen($path.$dir.$name,'w+');
fwrite($createImg,$newImageData);
fclose($createImg);

$_SESSION['dir'] = $path.$dir;
$_SESSION['file']= $name;

echo $dir.$name;
?>

del.php

<?php
session_start();
if(!$_POST)
return false;

$del = $_POST['del'];

if($del)
{
    @unlink($_SESSION['dir'].$_SESSION['file']);
    rmdir($_SESSION['dir']);
}

session_destroy();
?>

有什么问题和意见欢迎回复,吐槽楼主的人注定单身一辈子(o ̄∇ ̄o)♪

    原文作者:孤月
    原文地址: https://segmentfault.com/a/1190000002998496
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞