内容简介:之前恶搞了一张朋友的表情包,直接在百度上找了一个在线表情包制作器,突然灵光一闪,要是支持摄像头该多好,方便又快捷 (重点是省手机内存,不用拍照 :) ),二话不说,开始搬砖使用的第三方库
之前恶搞了一张朋友的表情包,直接在百度上找了一个在线表情包制作器,突然灵光一闪,要是支持摄像头该多好,方便又快捷 (重点是省手机内存,不用拍照 :) ),二话不说,开始搬砖
2. 预想的功能点
图片支持直接粘贴 和 拖拽 图片和文字缩放,支持鼠标滚轮 支持图片翻转 支持捕捉摄像头画面当素材
3. 撸页面
使用的第三方库
antd react-color react-draggle dom-to-image
页面 使用 React
+ Antd
方便快捷,三下五除二就搞定了
//每一行基本就是这样子 const operationRow = ({ icon = "edit", label, component }) => ( <Row className={`${prefix}-item`}> <Col span={labelSpan} className={`${prefix}-item-label`}> <Button type="dashed" icon={icon}> {label} </Button> </Col> <Col span={valueSpan} offset={offsetSpan} className={`${prefix}-item-input`} > {component} </Col> </Row> ); 复制代码
支持图片拖拽
dragArea.addEventListener( "dragleave", e => { this.stopAll(e); this.removeDragAreaStyle(); }, false ); //移动 dragArea.addEventListener( "dragover", e => { this.stopAll(e); this.addDragAreaStyle(); }, false ); dragArea.addEventListener( "drop", e => { this.stopAll(e); this.removeDragAreaStyle(); const files = e.dataTransfer.files; this.renderImage(Array.from(files)[0]); }, false ); 复制代码
支持 图片 粘贴,这个也很简单 绑定粘贴事件 拿到 event 里面的 data 渲染出来就行了
pasteHandler = e => { const { items, types } = e.clipboardData; if (!items) return; const item = items[0]; //只要一张图片 const { kind, type } = item; //kind 种类 ,type 类型 if (kind.toLocaleLowerCase() != "file") { return message.error("错误的文件类型!"); } const file = item.getAsFile(); this.renderImage(file); }; //粘贴图片 bindPasteListener = area => { area.addEventListener("paste", this.pasteHandler); }; 复制代码
渲染图片
renderImage = file => { if (file && Object.is(typeof file, "object")) { let { type, name, size } = file; if (!isImage(type)) { return message.error("无效的图片格式"); } this.setState({ loading: true }); const url = window.URL.createObjectURL(file); this.setState({ currentImg: { src: url, size: `${~~(size / 1024)}KB`, type }, scale: defaultScale, loading: false, loadingImgReady: true }); } }; 复制代码
其他就没啥好说的了,常规的页面布局
4. 生成图片
生成图片 本质上就是 利用 canvas 的 ctx.drawImage()
,
绘制文字
const canvas = document.createElement('cavans') const ctx = canvas.getContext('2d') canvas.width = "预览区域的宽" canvas.height = "预览区域的高" //图片 ctx.drawImage("URL",...attr) //文字 ctx.fillText(TEXT,...attr) //旋转图片 ctx.rotate(Math.PI/180 * 好多度) //缩放 也是 调用 drawImage, 改变 sy,sx 绘制的其实就实现缩放了 ctx.drawImage(URL,0,0,sx /scale,sy/scale,0,0,x,y) //转成图片 canvas.toDataURL('image/png',如果要压缩这里就填第二个参数) 复制代码
懂原理了 其实没必要一行一行这样写了 找到个 现成的 dom-to-image
的库,肥肠的不错,也是开源和组件化得魅力啊,利人利己
调用 api domToimage.toPng()
轻松搞定
drawMeme = () => { const { width, height, loadingImgReady,isCompress } = this.state; if (!loadingImgReady) return message.error("请选择图片!"); this.setState({ drawLoading: true }); const imageArea = document.querySelector(".preview-content"); const options = { width, height, } if(isCompress){ options.quality = defaultQuality } domToImage .toPng(imageArea, options) .then(dataUrl => { this.setState({ drawLoading: false }); Modal.confirm({ title: "生成成功", content: <img src={dataUrl} style={{ maxWidth: "100%" }} />, onOk: () => { message.success("下载成功!"); const filename = Date.now() const ext = isCompress ? 'jpeg' : 'png' var link = document.createElement("a"); link.download = `${filename}.${ext}`; link.href = dataUrl; link.click(); }, okText: "立即下载", cancelText: "再改一改" }); }) .catch(err => { message.error(err); this.setState({ drawLoading: false }); }); }; 复制代码
- MediaStream 实现 摄像头捕捉
要想拿到 MediaStream
, 调用 navigatar.mediaDevices()
即可, 如果想研究 webRTC
,这些 API 也是基础, 个人不是很感兴趣,就没研究,暂时只用到这个借口
navigator.mediaDevices .getUserMedia({ video: true, audio: true }) .then(stream => { const cameraUrl = window.URL.createObjectURL(stream); const hide = message.loading('盛世美颜即将出现...') //其他代码 this.setState( { cameraUrl, cameraVisible: true }, () => { setTimeout(()=>{ try { this.video.play(); } catch (err) { console.log(err); Modal.error({ title: "摄像头失败", content: err.message }); } finally{ hide() } },1000) } ); }) .catch((err)=>{ console.log(err) Modal.error({ title: "调用摄像头失败", content: err.toString() }); this.setState({ cameraVisible: false }); }); }) 复制代码
这时页面左上角 会弹出一个提示 问你是不是允许 使用摄像头,同意后 拿到 stream
,否则进入 cath
使用 URL.createObjectURL()
拿到一个临时的 url 链接
然后将 链接 设置成 <video src={临时 URL}/>
调用 video.play()
//jsx <video style={{ display:"block", margin:"0 auto" }} ref={video => (this.video = video)} src={cameraUrl} width={previewContentStyle.width} height={previewContentStyle.height} /> 复制代码
这时就会看见一个 帅气的脸庞 出现在了屏幕上 !
这时来到了最后一步,截取画面,也很简单 把 video 节点画在 canvas 上, 然后 toDataURL()
蹬蹬,搞定
screenShotCamera = () => { const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); const { width, height } = previewContentStyle; canvas.width = width; canvas.height = height; ctx.drawImage(this.video, 0, 0, width, height); const data = canvas.toDataURL("image/png"); message.success('截取摄像头画面成功!') this.setState({ currentImg: { src: data }, cameraVisible:false, scale: defaultScale, loading: false, loadingImgReady: true }); }; 复制代码
5. 下载图片
下载图片 基于 HTML5
的 download
属性很好实现
const filename = Date.now() const ext = isCompress ? 'jpeg' : 'png' const link = document.createElement("a"); link.download = `${filename}.${ext}`; link.href = dataUrl; link.click(); 复制代码
然后默认触发一次点击事件 搞定
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- iOS 上的相机捕捉
- 8千个城市2千万摄像头暴露:2018摄像头安全报告
- 为什么不建议在 for 循环里捕捉异常?
- 谷歌ARCore 1.6改善环境照明 抛光屏幕捕捉和记录
- 如何构建一个简单的摄像头组件
- [译] 充分利用多摄像头 API
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
数据结构与问题求解
韦斯 / 清华大学出版社 / 2011-8 / 89.50元
《数据结构与问题求解(Java语言版)(第4版)》是专为计算机科学专业的两个学期课程而设计的,从介绍什么足数据结构开始,继而对高级数据结构与算法进行分析。《数据结构与问题求解(Java语言版)(第4版)》以独特的方式,清晰地将每种数据结构的接口与其实现分离开来,即将如何使用数据结构与如何对数据结构编程相分离。《数据结构与问题求解(Java语言版)(第4版)》从抽象思维和问题求解的角度出发,为数据结......一起来看看 《数据结构与问题求解》 这本书的介绍吧!