对于前端开发而言,和图片打交道自然是家常便饭。曾经的项目开发之中,对图片的使用也经历过不少问题,cc最近准备延伸一下,全方位的探讨在前端的多种应用场景下的图片操作,从预览上传、加载到下载到本地,同时也会分析图片的处理方式并share一些和图片素材的自用网站。
一、图片的预览和上传
1. 图片的预览
图片的预览不只是根据后台接口返回的图片地址来显示图片,更多情况下,我们需要及时预览,就是在我们选择完图片之后就及时地显示在前台页面,而不是从api中向后台再次请求来的图片,这样的预览可以减少前后台的频繁交互,减少服务端无用的图片资源,简化我们的开发过程。
方案: 使用FileReader
实现前端的及时显示
1)FileReader的简介:
①FileReader
是H5中新增的对象, 负责读取文件内容
实例化: var reader = new FileReader();
②FileReader
通过一系列异步接口,在主线程中访问本地文件,方法有:
readAsText()
:按字符读取文本文件,返回文本字符串。默认UTF-8
readAsArrayBuffer(file)
: 按字节读取文件的内容,结果用ArrayBuffer
对象表示
readAsBinaryString(file)
: 按字节读取任意类型的文件,返回二进制字符串,这个方法不是为了读文件,而是为了存储文件
readAsDataURL(file)
: 读取文件内容,结果用data:url
的字符串形式表示,这段字符串的本质就是DataURL
。DataURL
是一种将文件(这个文件一般就是指图像或者能够嵌入到文档的文件格式) 嵌入到文档的方案。DataURL
是将资源转换为base64
编码的字符串形式,并且将这些内容直接存储在url
中 → 优化网站的加载速度和执行效率。
abort()
: 终止文件读取操作
③FileReader
提供了一个完整的事件模型,用来识别捕获文件时的状态,事件有:
事件 | 调用描述 |
---|---|
onabort | 读取操作被中断时 |
onerror | 读取操作发生错误时 |
onload | 读取操作成功完成时 |
onloadend | 读取操作完成时(不论成功/失败) |
onloadatart | 读取操作将要开始之前 |
onprogress | 读取数据过程中周期性调用 |
2)图片的本地预览
①通过FileReader的readAsDataURL()
方法,我们可以FileReader
是H5中新增的对象, 负责读取文件内容,跳过后台,直接 将本地图片显示在页面上。
<input type="file" id="imgFile" />
上传文件
<img id="file_img" height="200">
预览图片
var inputFile = document.getElementById("imgFile")
inputFile.onchange = function(){
var file = this.files[0]
if(file){
var reader = new FileReader();
reader.readAsDataURL(file); // 将图片转化为base64格式
reader.onload = function(){ // 成功读取文件
document.getElementById("file_img").src = this.result;
}
}else{
alert('图片预览失败')
}
}
②通过window.URL.createObjectURL
(blob/file),参数既可以是Blob对象,也可是File对象,这个方法可以根据传入的参数创建一个指向该擦书对象的URL,这个URL的生命仅存在于它被创建的这个文档中
function previewFile(){
var inputFile = document.getElementById("imgFile")
var file = inputFile.files[0]
if(file.size > 1024*1024*2){ // 限制图像的大小
alert('图片的大小不超过2MB!')
return false
}
// 创建图片的url
var imgUrl = window.URL.createObjectURL(file)
var preview = document.getElementById("file_img")
preview.setAttribute("src", imgUrl)
// document.getElementById("file_img").src = imgUrl
// 更改图片的url之后释放url
preview.onload = function(){
console.log('图片加载成功')
URL.revokeObjectURL(imgUrl)
}
}
注: 每次调用createObjectURL()
方法的时候,都会创建新的URL对象,所以在我们不需要的时候,必须调用URL.revokeObjectURL()
进行安全释放,为了保证更好的性能。
3)图片上传至服务器
主要有以下几种方式:
<input>
标签中的file
类型
file-input具备多个属性:accept、capture、multiple、files
示例:<input type="file" multiple id="imgFile" accept="image/*" />
let fileInput = document.getElementById('imgFile')
fileInput.onchange = function(e){
let fileList = this.files // 列出每个所选的文件对象
console.log(fileList)
}
FileReader
对象读取文件并上传
上面已经介绍过FileReader
就不再过多赘述- 利用
FormData
对象上传文件
FromData对象的使用:
1)用一些键值来模拟一系列表单控件name+value->queryString
2)异步上传二进制文件
主要使用append()方法:fromData.append(name,value,filename)
, 其中Blob对象的默认filename是"blob",File对象的默认文件名就是文件名
let file = document.querySelector('#imgFile').files[0]
const formData = new formData()
formData.append('usePicture', file, 'img.jpg')
axios
上传文件,并异步显示
axios
不仅可以做数据请求,也可以实现图片上传的功能,主要是设置header中的Content-Type
let config = {
headers: {
'Content-Type': 'nultipart/form-data'
}
}
this.$axios
.post('serverUrl', formData, config)
.then(res => {
console.log(res)
})
.catch(err => {
console.log(err)
})
axios 也可以使用onUploadProgress
监听上传进度
-
基于
form
表单和iframe
自己实现Ajax请求
form的target属性设置为iframe的name值,表示提交到url后返回的数据显示到iframe区域中
function loadIframe() { // 获取iframe内部的内容,并解析 var str_json = $('#iframe_1').contents().find('body').text() var obj = JSON.parse(str_json) if(obj.status){ var img = document.createElement('img') img.src = "/" + obj.path; $('#imgs').append(img); } }
二、图片的加载
除了正常的图片预览之外,还有不得不提的两种技术,预加载和懒加载
预加载: 提前加载图片,当用户需要查看时直接从本地缓存中渲染
懒加载: 一种按需加载的技术,主要目的是作为服务器前端的优化,减少请求数或者延迟请求数
技术本质:两者行为是相反的,一个是提前加载,一个是迟缓甚至不加载。懒加载对服务器前端有一定的缓解压力的作用,而预加载则会增加服务器端的压力。因此呢,我们主要使用的还是懒加载,它可以提升前端的性能,要隆重介绍下了。
(一) About Lazy Load
- 计算每张图片相对于屏幕顶端的距离offsetTop,如果图片还未出现就不需要加载,也就是如上图所示:图片到顶端距离 > 滚动条滚动的高度 + 浏览器可视高度, 只有当
offsetTop <= document.body.scrollTop + window.innerHeight
,图片才会加载
2)运用APIIntersectionObserver
,去动态检测元素是否出现在屏幕内,jquery_lazyLoad也支持API
主要介绍懒加载的几种实现方式:
- 原生js实现LazyLoad
根据上面1)中的原理:html中<img class="pic" alt="加载中" data-src="./images/1.png">
在IE9及以上的浏览器,可以使用
window.innerHeight
获取;但是在低版本的IE的标准模式中,可以使用document.documentElement.clientHeight
获取;因此关于viewHeight我们写代码时要考虑浏览器兼容的情况
const imgs = document.getElementByTagName('img') // 获取所有图片的标签
const viewHeight = window.innerHeight || document.documentElement.clientHeight // 获取可视区域的高度
const scrollTop = document.body.scrollTop || document.documentElement.scrollTop // 获取滚动条滑过的高度
let cnt = 0 // 记录当前统计到哪一张图片
function lazyLoad() {
// 遍历每一张图片,计算该图片是否加载,是否赋值真实src
imgs.map((imgItem)=>{
if(imgItem < scrollTop + viewHeight){
imgItem.src = imgItem.getAttribute('data-src') // 把真实的图片src赋值
}
})
}
// 写一个节流函数
function throttle(method, delay){
let timer = null
return function(){
let args = arguments
clearTimeout(timer)
timer = setTimeout(function(){
console.log(this)
method.apply(this.args)
},delay)
}
}
lazyLoad()
window.onscroll = throttle(lazyload, 200)
- 运用
IntersectionObserver
动态检测元素
检测是否会出现在屏幕内
// 获取观察器示例,changes是被观察的对象数组
var observer = new IntersectionObserver(fuction(changes){
console.log(changes)
changes.forEach(function(index, item){
if(item.intersectionRatio > 0 && item.intersectionRatio < 1){
item.target.src = item.target.dataset.src // target是被观察的目标元素,是一个DOM节点对象
}
})
})
function addObserver(){
var listItems = document.querySelectorAll('.img-item')
listItems.forEach(function(item){
// 实例的observer方法可以指定观察哪个DOM节点
observer.observe(item) // 开始观察,obsrver的参数是一个DOM节点对象
})
}
addObserver()
- Vue-lazyload使用
mint-UI组件库中的LazyLoad组件就是完全引用的‘vue-lazyload’
使用示例:
html部分: <li v-for="imgItem in imgList"><img v-lazy="imgItem"></li>
Vue.use(Lazyload)
new Vue({
el: #app,
data: {
imgList: ['imgurl1','imgurl2','imgurl3']
}
})
更多关于Vue-lazyload源码和原理的解析点击:Pick me up!~o( =∩ω∩= )m
4. jQuery-lazyload的使用
<img class="lazyload" data-original="ig/example.jpg" width="765" height="574">
<img class="lazyload" src="img/example.jpg" data-original="ig/example.jpg" width="765" height="574">
$('img.lazyload').lazyload();
更多详见源码:
(二) About PreLoad
虽然预先加载图片会增加服务器的压力,但必须承认的是预加载对于提升用户的体验非常有效,在访问页面时,可以自由自在体会到流畅的加载速度。尤其是对于一些主力军是图片的网站来说,使用预加载可以保证图片快速、无缝隙地发布,使用户有非凡的体验,增强网站的性能和可用性。
实现预加载的三种技术: 参考文章
-
使用CSS + JS 实现
实际上,单纯使用css就可以实现预加载,非常的简单、高效#preload-01 { background: url(./image-01.png) no-repeat -9999px -9999px; } #preload-02 { background: url(./image-02.png) no-repeat -9999px -9999px; } #preload-03 { background: url(./image-03.png) no-repeat -9999px -9999px; }
但是该方法下的加载时间却很长会和页面上的其他内容一起加载,增添整体页面的加载时间,仍有改进的余地
结合JS改进来推迟预加载的时间,直至页面加载完毕,所以添加JS代码:
var preLoader = function(){ if(document.getElementById){ // 获取类选择器的元素,并设置background属性 document.getElementById("preload-01").style.background = "url(./image-01.png) no-repeat -9999px -9999px"; document.getElementById("preload-02").style.background = "url(./image-02.png) no-repeat -9999px -9999px"; document.getElementById("preload-03").style.background = "url(./image-03.png) no-repeat -9999px -9999px"; } } function addLoadEvent(func){ var old_onload = window.onload; if(typeof(window.onload) != 'function'){ window.onload = func; }else{ window.onload = function(){ if(old_onload){ old_onload() } // 延迟preLoader()的加载时间,直到页面加载完毕 func() } } } addLoadEvent(preLoader)
-
使用JS实现
即便是使用JS对CSS加载进行优化,但涉及CSS加载,在实际过程中即便看起来高效但还是会花费很多时间。而最好的选择怕不是使用纯JS代码了,并且不用考虑浏览器的兼容性。
方案一: 适合大批量图片加载情况var images = new Array() function preload() { for(let i = 0; i < preload.arguments.length; i++){ images[i] = new Image() images[i].src = preload.arguments[i] } } // 把需要加载的图片的url放在其中 preload( "http://www.baidu.com/gallery/image1.jpg", "http://www.baidu.com/gallery/image2.jpg", "http://www.baidu.com/gallery/image3.jpg" )
方案二: 适合少量图片加载情况
function preLoader(){ if(documents.images) { var img1 = new Image() var img2 = new Image() var img3 = new Image() img1.src = "path/to/image1.jpg" img2.src = "path/to/image1.jpg" img3.src = "path/to/image1.jpg" } } function addLoadEvent(func){ // ...同上面的延迟加载功能函数 } addLoadEvent(preLoader)
-
使用Ajax实现
还有一种更秀的操作——使用Ajax实现预加载。这种方法可以利用
DOM
,不仅可以预加载图片,还会预加载CSS、Javascript
等相关的东西。比起直接用JS,它的闪光点在于JS和CSS的加载不会影响当前页面,更加简洁高效。window.onload = function(){ setTimeout(function(){ // XHR去请求js和css对象 var xhr = new XMLHttpRequest() xhr.open('GET', 'http://domain.tld/preload.js') xhr.send('') xhr = new XMLHttpRequest() xhr.open('GET', 'http://domain.tld/preload.js') xhr.send('') new Image().src = "http://domain.tld/preload.png" // 预加载图片 }, 1000); // 1s超时,防止脚本挂起 }
三、图片的下载
除了后台直接给url点开就可以下载的方式,前端实现图片的下载主要有三种方案:
-
通过
<a>
的download
属性html中的a标签中自带下载属性,因此我们可以这样实现下载:
<a href = "javascript:void()" download="pic.jpg" id="download">下载本图片</a>
在上面1.2.1使用FileReader接口预览代码的上添加下载功能:
var inputFile = document.getElementById("imgFile") inputFile.onchange = function(){ var file = this.files[0] if(file){ var reader = new FileReader(); reader.readAsDataURL(file); reader.onload = function(e){ // 预览图片,this.result/e.target.result都可以 document.getElementById("file_img").src = e.target.result; // 点击下载图片 var downloadImg = document.getElementById("download"); downloadImg.setAttribute("href", e.target.result); //给a标签设置href } }else{ alert('图片加载失败') } }
注:除了考虑浏览器的兼容问题之外,还有同源策略的限制,也就是说
href
指向路径必须与当前网站同源,否则就会出现下载失效或者只能下载无法改名之类的问题MDN a标签说明文档 在很多实际情况下,这种方案一并不是可行的,因为我们需要下载的图片不一定是放在后台,跨域限制使得我们无法正常下载。
-
通过Javascript动态创建
<a>
并设置download属性原理和限制同上,代码如下(不支持IE):
function download(url, name){ const aLink = document.createElement('a') aLink.download = name aLink.href = url // 触发a的单击事件 aLink.dispatchEvent(new MouseEvent('click', {})) }
以导出
canvas
图像为例:
<canvas id = "canvas" > </canvas>
const canvas = document.getElementById('canvas') download(canvas.toDataURL('image/png'),'name.png')
进化版: 只要浏览器可以正常打开这个图片,就可以下载
原理: 点击下载之后,新建一个隐藏的canvas ,大小和图片本身的大小一致,然后保存这个数据流,就启动了浏览器的下载。(这时候图片是以文字流的形式下载的)function downloadImage(url, name){ let image = new Image() // 解决跨域Canvas污染问题 image.setAttribute("crossOrigin", anonymous) image.onload = function(){ let canvas = document.getElementById('canvas') canvas.width = image.width canvas.height = image.height let context = canvas.getContext("2d") context.drawImage(image, 0, 0, image.width, image.height) let imgUrl = canvas.toDatatURL("image/png") // 得到图片的base64编码数据 let a = document.createElement("a") let event = new MouseEvent("click") // 创建一个单击事件 a.download = name || "photo" // 设置图片名称 a.href = url // 将生成的URL设置为a.href属性 a.dispatchEvent(event) // 触发单击事件 } image.src = url }
-
通过Javascript创建
<frame>
(不推荐)<iframe height="0" width = "0" src="pic.jpg" name="saveImage" id="saveImage"></iframe>
<a href="#" onclick="saveImage.document.execCommand('saveAs')">Download</a>
document.execCommand('SaveAs')
中 SaveAs 是个非标准值,主要用来兼容 ie 不支持<a>
标签 download 属性的场景window.frames["iframeName"].document
受到同源策略的影响,如果图片地址跨域,是无法访问的<frame>
的属性和方法
此外,还可以设置response, header, content-type
轮播图的实现
在电商平台中,轮播图的应用较为广泛:
-
JS中轮播图的实现原理:
图片轮播的原理就是图片排成一行,然后准备一个只有一张图片大小的容器,对这个容器设置超出部分隐藏,来控制定时器让这些图片整体左移或者右移,这样呈现出来的效果就是图片在轮播 -
多个轮播的实现: 封装一个轮播的组件,供多处使用
-
Vue中的轮播组件应用实例
之前在复现去哪儿项目的时候,涉及到了广告轮播图的使用,主要使用的是功能强大的swiper组件:具体的实现:
1)Swiper.vuemarkdown编辑器暂时不支持直接放vue代码和html代码,所以分开放
export default{ name: 'HomeSwiper', props: { list: Array }, data(){ return { swiperOption: { // 自定义轮播图的属性 pagination: '.swiper-pagination', loop: true } } } }
.wrapper >>> .swiper-pagination-bullet-activate{ background: red !important } .wrapper{ overflow: hidden width: 100% height: 0 padding-bottom: 31.25% /*或者直接定义height: 31.25vm,保持宽高比例*/ background-color: darkgrey .swiper-img{ width: 100% } }
2)Home.vue中
使用自定义的Swiper组件,<home-swiper :list="swiperList"></home-swiper>
import HomeSwiper from './components/Swiper' export default{ name: 'Home', components: { HomeSwiper }, data(){ swiperList: [] // 轮播的内容,图片信息之类,数据示例如下: // swiperList: [{ // id: '0001', // imgUrl: 'https://img1.qunarzz.com/sight/p0/1606/be/be7426985c756fc7e2.img.jpg_600x330_4dc81148.jpg' // }, { // id: '0002', // imgUrl: 'https://img1.qunarzz.com/sight/p0/1412/ad/32a5e0cd8baa07f908eab28e03d5a89f.water.jpg_600x330_353965dc.jpg' // }, { // id: '0003', // imgUrl: 'https://img1.qunarzz.com/sight/p0/1603/b5/b55923ced74910b990.water.jpg_600x330_05ff4419.jpg' // }] } }
图片的压缩
通常在移动端项目的开发中,图片的大小非常影响加载性能,图片过大十分耗费用户流量,延缓加载时间,会使得用户的体验大打折扣。对图片进行压缩是前端优化的重中之重,在很多地方我们需要对其进行压缩,比如在上传之前对手机里选择的高达好几M的图片进行压缩。图片压缩的常见方式:插件压缩、Canvas压缩等
- tinypng插件压缩
可以使用tinypng插件实现压缩项目图片,毕竟一一官网上传太麻烦了。
官方给出了node包,gulp-tinypng,但是需要官方注册邮件,拿到key之后每月限免500张。
使用gulp-tinypng-compress
插件的具体实现:
var gulp = require('gulp');
var tinypng = require('gulp-tinypng-compress');
gulp.task("tinypng", function(){
gulp.src('img/**/*.{png,jpg,jpeg}')
.pipe(tinypng({
key: '-HERE IS YOUR API KEY-',
sigFile: 'images/.tinypng-sigs',
log: true
})).on('error', function(err) {
console.error(err.message);
})
.pipe(gulp.dest('dis/img'));
});
- 利用Canvas压缩图片
也就是使用js实现图片压缩的效果,原理:
- 利用
canvas
的drawImage
将目标图片画到画布上 - 利用画布调整绘制尺寸,以及导出的
quality
,确定压缩的程度 - 利用
canvas
的toDataURL
或者toBlob
可以将画布上的内容导出成 base64 格式的数据
Q&A:
- ios下图片翻转
使用import EXIF from 'exif-js'
来获取手机的方向,然后对canvas
的宽高进行处理 - 压缩到特定大小
let imgDataLength = dataUrl.length
;
获取到数据后,判断压缩后的图片大小是否满足需求,否则就降低尺寸以及质量,再次压缩 - quality对png无效
因此导出的格式统一为jpeg, 透明背景填充为白色
// 填充白色背景
ctx.fillStyle = fillBgColor;
ctx.fillRect(0, 0, size.w, size.h);
具体代码实现:
/**
* 文件读取并通过canvas压缩转成base64
* @param files
* @param callback
*/
//EXIF js 可以读取图片的元信息 https://github.com/exif-js/exif-js
import EXIF from 'exif-js';
// 压缩图片时 质量减少的值
const COMPRESS_QUALITY_STEP = 0.03;
const COMPRESS_QUALITY_STEP_BIG = 0.06;
// 压缩图片时,图片尺寸缩放的比例,eg:0.9, 等比例缩放为0.9
const COMPRESS_SIZE_RATE = 0.9;
let defaultOptions = {
removeBase64Header: true,
// 压缩后允许的最大值,默认:300kb
maxSize: 200 * 1024,
fillBgColor: '#ffffff'
};
/**
* 将待上传文件列表压缩并转换base64
* !!!! 注意 : 图片会默认被转为 jpeg , 透明底会加白色背景
* files : 文件列表 ,必须是数组
* callback : 回调,每个文件压缩成功后都会回调,
* options :配置
* options.removeBase64Header : 是否需要删除 'data:image/jpeg;base64,'这段前缀,默认true
* @return { base64Data: '',fileType: '' }, //fileType强制改为jpeg
*/
export function imageListConvert(files, callback, options = {}) {
if (!files.length) {
console.warn('files is null');
return;
}
options = { ...defaultOptions, ...options };
// 获取图片方向--iOS拍照下有值
EXIF.getData(files[0], function() {
let orientation = EXIF.getTag(this, 'Orientation');
for (let i = 0, len = files.length; i < len; i++) {
let file = files[i];
let fileType = getFileType(file.name);
//强制改为jpeg
fileType = 'jpeg';
let reader = new FileReader();
reader.onload = (function() {
return function(e) {
let image = new Image();
image.onload = function() {
let data = convertImage(
image,
orientation,
fileType,
options.maxSize,
options.fillBgColor
);
if (options.removeBase64Header) {
data = removeBase64Header(data);
}
callback({
base64Data: data,
fileType: fileType
});
};
image.src = e.target.result;
};
})(file);
reader.readAsDataURL(file);
}
});
}
/**
* 将 image 对象 画入画布并导出base64数据
*/
export function convertImage(
image,
orientation,
fileType = 'jpeg',
maxSize = 200 * 1024,
fillBgColor = '#ffffff'
) {
let maxWidth = 1280,
maxHeight = 1280,
cvs = document.createElement('canvas'),
w = image.width,
h = image.height,
quality = 0.9;
/**
* 这里用于计算画布的宽高
*/
if (w > 0 && h > 0) {
if (w / h >= maxWidth / maxHeight) {
if (w > maxWidth) {
h = (h * maxWidth) / w;
w = maxWidth;
}
} else {
if (h > maxHeight) {
w = (w * maxHeight) / h;
h = maxHeight;
}
}
}
let ctx = cvs.getContext('2d');
let size = prepareCanvas(cvs, ctx, w, h, orientation);
// 填充白色背景
ctx.fillStyle = fillBgColor;
ctx.fillRect(0, 0, size.w, size.h);
//将图片绘制到Canvas上,从原点0,0绘制到w,h
ctx.drawImage(image, 0, 0, size.w, size.h);
let dataUrl = cvs.toDataURL(`image/${fileType}`, quality);
//当图片大小 > maxSize 时,循环压缩,并且循环不超过5次
let count = 0;
while (dataUrl.length > maxSize && count < 10) {
let imgDataLength = dataUrl.length;
let isDoubleSize = imgDataLength / maxSize > 2;
// 质量一次下降
quality -= isDoubleSize
? COMPRESS_QUALITY_STEP_BIG
: COMPRESS_QUALITY_STEP;
quality = parseFloat(quality.toFixed(2));
// 图片还太大的情况下,继续压缩 。 按比例缩放尺寸
let scaleStrength = COMPRESS_SIZE_RATE;
w = w * scaleStrength;
h = h * scaleStrength;
size = prepareCanvas(cvs, ctx, w, h, orientation);
//将图片绘制到Canvas上,从原点0,0绘制到w,h
ctx.drawImage(image, 0, 0, size.w, size.h);
console.log(`imgDataLength:${imgDataLength} , maxSize --> ${maxSize}`);
console.log(`size.w:${size.w}, size.h:${size.h}, quality:${quality}`);
dataUrl = cvs.toDataURL(`image/jpeg`, quality);
count++;
}
console.log(`imgDataLength:${dataUrl.length} , maxSize --> ${maxSize}`);
console.log(`size.w:${size.w}, size.h:${size.h}, quality:${quality}`);
cvs = ctx = null;
return dataUrl;
}
/**
* 准备画布
* cvs 画布
* ctx 上下文
* w : 想要画的宽度
* h : 想要画的高度
* orientation : 屏幕方向
*/
function prepareCanvas(cvs, ctx, w, h, orientation) {
cvs.width = w;
cvs.height = h;
//判断图片方向,重置canvas大小,确定旋转角度,iphone默认的是home键在右方的横屏拍摄方式
let degree = 0;
switch (orientation) {
case 3:
//iphone横屏拍摄,此时home键在左侧
degree = 180;
w = -w;
h = -h;
break;
case 6:
//iphone竖屏拍摄,此时home键在下方(正常拿手机的方向)
cvs.width = h;
cvs.height = w;
degree = 90;
// w = w;
h = -h;
break;
case 8:
//iphone竖屏拍摄,此时home键在上方
cvs.width = h;
cvs.height = w;
degree = 270;
w = -w;
// h = h;
break;
}
// console.log(`orientation --> ${orientation} , degree --> ${degree}`);
// console.log(`w --> ${w} , h --> ${h}`);
//使用canvas旋转校正
ctx.rotate((degree * Math.PI) / 180);
return { w, h };
}
/**
* 截取 ‘data:image/jpeg;base64,’,
* 截取到第一个逗号
*/
export function removeBase64Header(content) {
if (content.substr(0, 10) === 'data:image') {
let splitIndex = content.indexOf(',');
return content.substring(splitIndex + 1);
}
return content;
}
export function getFileType(fileName = '') {
return fileName.substring(fileName.lastIndexOf('.') + 1);
}
export function checkAccept(
file,
accept = 'image/jpeg,image/jpg,image/png,image/gif'
) {
return accept.toLowerCase().indexOf(file.type.toLowerCase()) !== -1;
}
网站收藏
推荐几个比较常用的网站,值得收藏:
好用的切图工具
- Photoshop CC
- XD
- PxCook
- FastStone Capture截图工具
如果你看到这里了,那么你将会收获一件小干货
——HOT面试题分享:如何选择图片的格式(例如png,webp(B_Cornelius))
关于图片的总结大概就是这些了,忽然发现这篇文章像极了cc最心爱的螺蛳粉(又臭又长) hhhhhhhhhh但整理总结的过程十分迷人的