html部分:
<button id="buttonID" type="button" style="height: 28px;">下载图片</button>
<div class="" id= "mainPage" ></div>
js部分:
<!--这里的库文件请从文章最末尾的参考文献中下载,请务必注意,以免版本不吻合-->
<script type="text/javascript" src="js/html2canvas.js"></script>
<script type="text/javascript">
var imgdata = "";
var main = {
init:function(){
main.setListener();
},
//设置监听事件
setListener:function(){
var btnShare = document.getElementById("buttonID");
btnShare.onclick = function(){
main.html2Canvas();
}
},
//获取像素密度
getPixelRatio:function(context){
var backingStore = context.backingStorePixelRatio ||
context.webkitBackingStorePixelRatio ||
context.mozBackingStorePixelRatio ||
context.msBackingStorePixelRatio ||
context.oBackingStorePixelRatio ||
context.backingStorePixelRatio || 1;
return (window.devicePixelRatio || 1) / backingStore;
},
//绘制dom 元素,生成截图canvas
html2Canvas: function () {
// 需要绘制的部分的 (原生)dom 对象 ,注意容器的宽度尽量不要使用百分比,使用固定宽度,避免缩放问题
var shareContent = document.getElementById("mainPage");
console.log(shareContent);
/*有时候会出现边缘空白区域会出现黑色或不想要的的背景,下面三个行代码是为了调节这个产生的,
他们可以改变紧接着下面的offsetWidth和offsetHeight,这里可以自行调整,不用的话可以注解掉*/
/*
$("#mainPage").css("margin-top","-149px");
$("#mainPage").css("margin-left","-258px");
$("#mainPage").css("margin-right","-149px");
*/
// 获取(原生)dom 宽度
var width = shareContent.offsetWidth;
// 获取(原生)dom 高
var height = shareContent.offsetHeight;
shareContent.offsetTop = 0;
//元素距离顶部的偏移量
var offsetTop = shareContent.offsetTop;
//var offsetTop = 300;
alert("下载图片需要一两秒中,请耐心等待!~~");
//创建canvas 对象
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
//获取像素密度的方法 (也可以采用自定义缩放比例,比如这里我就自定义缩放比例为5)
//var scaleBy = main.getPixelRatio(context);
//自定义缩放比例为5,数字越大,图片越清晰,同样越大,编码越慢,以我经验4倍就非常清晰了
var scaleBy = 5;
//下面两行代码可配合35/36/37行代码调整生成图片的显示位置
//这里 由于绘制的dom 为固定宽度,居中,所以没有偏移
canvas.width = (width) * scaleBy;
// 注意高度问题,由于顶部有个距离所以要加上顶部的距离,解决图像高度偏移问题
canvas.height = (height + offsetTop+76) * scaleBy;
context.scale(scaleBy, scaleBy);
var opts = {
allowTaint:true,//允许加载跨域的图片
tainttest:true, //检测每张图片都已经加载完成
scale:scaleBy, // 添加的scale 参数
canvas:canvas, //自定义 canvas
//logging: true, //日志开关,发布的时候记得改成false
width:width, //dom 原始宽度
height:height, //dom 原始高度
};
html2canvas(shareContent, opts).then(function (canvas) {
//这里很明显是最重要的一句代码--获取生成的图片base64编码
var pageData = canvas.toDataURL('image/jpeg', 1.0);
console.log(pageData);
//这里可以对存储图片的路径下的原有图片做一个清理(自行决定,可以注解)
/*
$.ajax({
type:"GET",
async:false,
url:"php/delImgs.php",
dataType:"json",
error: function(){
},
success:function(data){
//alert("ok");
}
});
*/
//alert("清理完毕!~~");
//这里是定义了图片的名字,请自行调整
var title = "生成图片1";
//下载图片到服务器
$.ajax({
type:"POST",
async:false,
url:"php/saveImgs.php",
dataType:"json",
data:{imgurl:pageData,name:title},
error: function(){
},
success:function(data){
//alert("download success");
}
});
//从服务器获取图片,在浏览器上下载下来(这里模拟的form表单下载js代码附在下方,action的PHP代码也附在下方,其他下载方式请自行寻找)
$.download('php/downloadByForm.php','find='+title,'post' );
//这里其实可以再次调用35/36/37行代码(修改相应的值为原有值)恢复页面到原有的状态
});
}
};
//最后运行代码
main.init();
</script>
<script>
//下载js
jQuery.download = function(url, data, method){ // 获得url和data
if( url && data ){
// data 是 string 或者 array/object
data = typeof data == 'string' ? data : jQuery.param(data); // 把参数组装成 form的 input
var inputs = '';
jQuery.each(data.split('&'), function(){
var pair = this.split('=');
inputs+='<input type="hidden" name="'+ pair[0] +'" value="'+ pair[1] +'" />';
}); // request发送请求
jQuery('<form action="'+ url +'" method="'+ (method||'post') +'">'+inputs+'</form>').appendTo('body').submit().remove();
};
};
</script>
php部分:
saveImgs.php
<?php
$image = isset($_POST['imgurl']) ? $_POST['imgurl'] : '';
$imageName = isset($_POST['name']) ? $_POST['name'] : '';
//$imageName = "25220_".date("His",time())."_".rand(1111,9999).'.png';
$imageName = $imageName.'.jpg';
//由于imageName中可能有汉字,所以需要转码,纯英文的话,就不需要了
$imageName = iconv("utf-8", "gbk", $imageName);
if (strstr($image,",")){
$image = explode(',',$image);
$image = $image[1];
}
$path = "tmp/";
$imageSrc= $path."/". $imageName; //图片名字
$r = file_put_contents('/data/'.$imageSrc, base64_decode($image));//返回的是字节数
if (!$r) {
echo json_encode(array('data'=>null,"code"=>1,"msg"=>"图片生成失败"));
}else{
echo json_encode(array('data'=>1,"code"=>0,"msg"=>"图片生成成功"));
}
delImgs.php
<?php
function delFileUnderDir( $dirName )
{
if ( $handle = opendir( "$dirName" ) ) {
while ( false !== ( $item = readdir( $handle ) ) ) {
if ( $item != "." && $item != ".." ) {
if ( is_dir( "$dirName/$item" ) ) {
delFileUnderDir( "$dirName/$item" );
} else {
if( unlink( "$dirName/$item" ) )echo "成功删除文件: $dirName/$item\n";
}
}
}
closedir( $handle );
}
}
//路径和保存图片的路径保持一直就行了,看自己情况
$pathDir = 'tmp';
delFileUnderDir($pathDir);
downloadByForm.php
<?php
/**
* 下载文件
* @param string $file
* 被下载文件的路径
* @param string $name
* 用户看到的文件名
*/
$path = isset($_POST['find']) ? $_POST['find'] : '';
$imageName = $path;
$imageName = iconv("utf-8", "gbk", $imageName);
function download($imageName){
$file = "tmp/".$imageName.".jpg";
$name = $imageName;
$fileName = $name ? $name : pathinfo($file,PATHINFO_FILENAME);
$filePath = realpath($file);
$fp = fopen($filePath,'rb');
if(!$filePath || !$fp){
header('HTTP/1.1 404 Not Found');
echo "Error: 404 Not Found.(server file path error)";
exit;
}
$fileName = $fileName .'.'. pathinfo($filePath,PATHINFO_EXTENSION);
$encoded_filename = urlencode($fileName);
$encoded_filename = str_replace("+", "%20", $encoded_filename);
header('HTTP/1.1 200 OK');
header( "Pragma: public" );
header( "Expires: 0" );
header('Content-type: image/jpeg');
header("Content-Length: ".filesize($filePath));
header("Accept-Ranges: bytes");
header("Accept-Length: ".filesize($filePath));
//Content-Disposition: attachment; filename=\"" . $file_name."\""
//header("content-disposition:attachment;filename=".$filename);
$ua = $_SERVER["HTTP_USER_AGENT"];
if (preg_match("/MSIE/", $ua)) {
header('Content-Disposition: attachment; filename="' . $encoded_filename . '"');
} else if (preg_match("/Firefox/", $ua)) {
header('Content-Disposition: attachment; filename=' . $fileName );
} else {
header('Content-Disposition: attachment; filename="' . $fileName . '"');
}
//ob_end_clean(); //<--有些情况可能需要调用此函数
// 输出文件内容
fpassthru($fp);
exit;
}
download($imageName);
?>
参考文献