整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

使用JavaScript+CSS3+SVG clip

使用JavaScript+CSS3+SVG clipPath实现自适应被裁剪图片对象实例

SS3中引入的clip-path(裁剪路径)属性是一个很强大的特性。clip-path的含义如下图所示,好比剪纸一样,你用剪刀沿着某条路径把目标对象(图像或元素)裁剪成我们想要的形状。

clip-path支持多种方式,如基本的图形(多边形polygon(), 圆形circle(), inset() (用来定义内部矩形), 和椭圆 ellipse()),也支持直接引用SVG中的clipPath元素。先看二个效果图

通常简单的裁剪,我们直接使用基本图形,或者使用在线工具辅助生成,我们推荐使用:

http://www.ikinsoft.com/clippath/clippath.html

来生成一些简单的裁剪路径,代码如下:

/* Using a CSS basic shape function */

.element {

clip-path: polygon(...); /* or one of the other shape functions */

}

对于更为复杂的裁剪,使用SVG无疑是更好的选择,我们可以在AI或Inkscape中创作好矢量图,然后根据其路径(path)数据生成相应的clipPath元素,然后在CSS3中直接引用,代码如下:

/* Referencing an SVG clipPath */

.element {

clip-path: url(#svgClipPathID);

}

但是在使用SVG clipPath元素时,经常会遇到单位不匹配的情况,因为通常通过工具生成的g元素,会应用一些变换(如位移和缩放):

<g transform="translate(0.000000,126.000000) scale(0.100000,-0.100000)"><clipPath>your paths here</clipPath></g>

而在CSS3直接引用clipPath时,不会自动去处理这些变换,需要我们自己来处理,

把path数据转换成百分比,然后给clipPath添加clipPathUnits="objectBoundingBox"属性来自适应:

<svg width="0" height="0">

<defs>

<clipPath id="svgPath" clipPathUnits="objectBoundingBox">

<!-- your paths here -->

</clipPath>

</defs>

</svg>

clipPathUnits 属性用来指定<clipPath>元素内容的坐标系,有2种取值:

clipPathUnits="userSpaceOnUse | objectBoundingBox"

userSpaceOnUse表示当前网页所使用的屏幕坐标系,而objectBoundingBox则把坐标空间的原点调整到被裁剪对象的左上角,坐标空间的长宽设定为该元素的长宽。

生成polygons图形clipPath数据的JavaScript代码,如下:

$.each(shape_array.polygon, function (i, shape) {

paths='';

$.each(shape.coords, function (i, coord) {

type="polygon";

var x=coord[0] + "%";

var y=coord[1] + "%";

var path='clip-path: polygon()';

var coord='';

if (i==shape.coords.length - 1) {

// last coordinate to add, omits a comma at the end

paths +=x + ' ' + y;

var clip_path='polygon(' + paths + ')';

appendFigure(clip_path, shape);

} else {

// loops through each coordinate and adds it to a list to add

paths +=x + ' ' + y + ', ';

}

});

下截图:

点击文件选择框,我们不妨选一张尺寸比较大的图片,例如下面这种2M多的钓鱼收获照:

于是图片歘歘歘地传上去了:

此时我们点击最终上传完毕的图片地址,会发现原来2M多3000多像素宽的图片被限制为400像素宽了:

保存到本地会发现图片尺寸已经变成只有70K了:

以上就是图片前端压缩并上传demo的完整演示。

二、实现原理

要想使用JS实现图片的压缩效果,原理其实很简单,核心API就是使用canvas的drawImage()方法。

Canvas本质上就是一张位图,而drawImage()方法可以把一张大大的图片绘制在小小的Canvas画布上,不久等同于图片尺寸压缩了?

对于本案例的压缩,使用的5个参数的API方法:

context.drawImage(img, dx, dy, dWidth, dHeight);复制代码

各参数具体含义可以参见“Canvas API中文文档-drawImage”,这里不展开。

举例:

一张图片(假设图片对象是img)的原始尺寸是4000*3000,现在需要把尺寸限制为400*300大小,很简单,原理如下代码示意:

var canvas=document.createElement('canvas');
var context=canvas.getContext('2d');
canvas.width=400;
canvas.height=300;
// 核心JS就这个
context.drawImage(img,0,0,400,300);复制代码

把大图片画在一张小画布上,压缩就这么实现了,是不是简单的有点超乎想象。

三、如果想要上传或下载?

如果想要上传图片或者下载图片,可以使用canvas.toDataURL()或者canvas.toBlob()方法先进行转换。

1. canvas.toDataURL()

语法如下:canvas.toDataURL(mimeType, qualityArgument)复制代码

可以把画布转换成base64格式信息图像信息,纯字符的图片表示法。

其中:

mimeType表示canvas导出来的base64图片的类型,默认是png格式,也即是默认值是'image/png',我们也可以指定为jpg格式'image/jpeg'或者webp等格式。file对象中的file.type就是文件的mimeType类型,在转换时候正好可以直接拿来用(如果有file对象)。

qualityArgument表示导出的图片质量,只要导出为jpg和webp格式的时候此参数才有效果,默认值是0.92,是一个比较合理的图片质量输出参数,通常情况下,我们无需再设定。

更多关于toDataURL()方法的信息可以参见“Canvas API中文文档-toDataURL()”。

2. canvas.toBlob()方法

语法如下:canvas.toBlob(callback, mimeType, qualityArgument)复制代码

可以把画布转换成Blob文件,通常用在文件上传中,因为是二进制的,对后端更加友好。

和toDataURL()方法相比,toBlob()方法是异步的,因此多了个callback参数,这个callback回调方法默认的第一个参数就是转换好的blob文件信息,本文一开始的demo案例中的文件上传就是将canvas图片转换成二进制的blob文件,然后再ajax上传的,代码如下:

// canvas转为blob并上传
canvas.toBlob(function (blob) {
 // 图片ajax上传
 var xhr=new XMLHttpRequest();
 // 开始上传
 xhr.open("POST", 'upload.php', true);
 xhr.send(blob); 
});复制代码

更多关于toBlob()方法的信息可以参见“Canvas API中文文档-toBlob()”。

一旦有了可传输的图像数据,上传下载就好实现了。例如下载前端压缩好的图片,可以参考我上一篇在掘金发布的文章:“纯JS生成并下载各种文本文件或图片”。

四、总结

经过“图片→canvas压缩→图片”三步曲,我们完成了图片前端压缩功能。

作者:张鑫旭

链接:https://juejin.im/post/5bec3c6cf265da614312a0fa

来源:掘金

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

cropperjs是一款基于JavaScript的网页端图片裁剪插件,可能相对于图片预览来说,图片的裁剪使用场景貌似并不是很多,但是图片预览插件又要比裁剪插件容易找到,而且从实现难度上来说也不及图片裁剪,今天我们就一起来看看这款良心的图片裁剪插件——Cropperjs






Github

作者的几个经典作品都在Github上,并且都获得不菲的stars,感谢作者提供这么好用的免费插件

https://github.com/fengyuanchen/cropperjs

特性

  • 支持39个配置选项
  • 支持27 种方法
  • 支持6 场事件
  • 支持触摸(移动)
  • 支持缩放
  • 支持旋转
  • 支持缩放(翻转)
  • 支持多种作物
  • 支持在画布上裁剪
  • 支持在画布上通过画布裁剪图像
  • 支持翻译Exif方向信息
  • 跨浏览器支持
  • 安装

    使用npm安装或者直接下载编译好的js文件

    npm install cropperjs
    <link  href="/path/to/cropper.css" rel="stylesheet">
    <script src="/path/to/cropper.js"></script>

    使用

    • 语法
    new Cropper(element[, options])
  • element
    1. 类型:HTMLImageElement或HTMLCanvasElement
    2. 用于裁剪的目标图像或画布元素。
  • options(可选)
    1. 类型: Object裁剪配置选项。

    使用案例:

    <div>
      <img id="image" src="picture.jpg">
    </div>
    img {
      display: block;
    
      /* This rule is very important, please don't ignore this */
      max-width: 100%;
    }
    import Cropper from 'cropperjs';
    
    const image=document.getElementById('image');
    const cropper=new Cropper(image, {
      aspectRatio: 16 / 9,
      crop(event) {
        console.log(event.detail.x);
        console.log(event.detail.y);
        console.log(event.detail.width);
        console.log(event.detail.height);
        console.log(event.detail.rotate);
        console.log(event.detail.scaleX);
        console.log(event.detail.scaleY);
      },
    });

    PS:具体的配置选项可以到Github上查看相关文档,同时也提供了一个在线的预览demo

    在线预览Demo

    https://fengyuanchen.github.io/cropperjs/


    总结

    cropperjs是一个纯前端的图片裁剪工具,同时笔者之前文章也介绍过和cropperjs同源作者的另一个佳作viewerjs,这是一个优秀的前端图片预览插件,功能丰富,配置简单,推荐使用,enjoy it!

    https://www.toutiao.com/i6775436136027259404/