js图片剪切,支持拖动、缩放

trace.img.js

支持拖动、缩放等,看演示,(使用缩放请把代码"operate.show()"取消注释),因方便使用了部分es6语法,需要兼容性的请自行修改

效果演示:

(function(root, factory) {
	if(typeof define === 'function' && define.amd) {
		define(['jquery']);
	} else if(typeof exports === 'object') {
		module.exports = factory(require('jquery'));
	} else {
		root.TraceImg = factory(root.jQuery);
	}
}(this, function($) {
	let util = {
		windowHeight: $(window).height(),
		windowWidth: $(window).width(),
		bodyHeight: $(document.body).outerHeight(true),
		bodyWidth: $(document.body).outerWidth(true)
	},
	imageCut = (() => {
		let files = {},
		cutoutimg = (e) => {
			let dom = $(e.dom),
				w = e.cut.width,
				h = e.cut.height,
				time = new Date().getTime(),
				showW = e.show.width,
				showH = e.show.height,
				imgZoom = 1,
				_img = null,
				_img_info = {},
				canvasId = null,
				showDom = (() => {
					dom.after(`<div id='show_${time}'></div>`)
					return $(`#show_${time}`)
				})(),
				operate = (() => {
					showDom.after(`<div style='width:${showW}px;display:none;' id='operate_${time}'><a href='javascript:;'><img alt='缩小'/></a><a href='javascript:;'><img alt='放大'/></a></div>`)
					return $(`#operate_${time}`)
				})(),
				nowImg = (() => {
					let defaultStyle = {
						width: w,
						height: h,
						position: "relative"
					},
					parentArea = (() => {
						showDom.after(`<div id='nowimg_${time}'><img width='100%;height:100%;'/><canvas style='display:none;' width='${w}' height='${h}'></canvas></div>`)
						return $(`#nowimg_${time}`)
					})()
					return {
						parentArea: parentArea,
						dom: $(parentArea.children()[0]),
						canvasJsDom: parentArea.children()[1],
						parentBottomStyle: $.extend({
							top: 10,
							left: 0
						}, defaultStyle),
						parentRightStyle: $.extend({
							bottom: showH,
							left: showW + 10
						}, defaultStyle)
					}
				})(),
				showStyle = {
					width: showW,
					height: showH,
					overflow: "hidden",
					position: "relative"
				},
				overstory = null,
				overstoryOffetShowDomX = (showW - w)/2,
				overstoryOffetShowDomY = (showH - h)/2,
				overstoryStyle = {
					width: w,
					height: h,
					position: "absolute",
					top: 0,
					left: 0,
					'border-top': overstoryOffetShowDomY + "px solid #ccc",
					'border-bottom': overstoryOffetShowDomY + "px solid #ccc",
					'border-left': overstoryOffetShowDomX + "px solid #ccc",
					'border-right': overstoryOffetShowDomX + "px solid #ccc",
					'border-style': "solid",
					opacity: 0.5
				},
				addOverstory = () => {
					showDom.append(`<div id='overstory_${time}'></div>`)
					overstory = $(`#overstory_${time}`)
					overstory.css(overstoryStyle)
					overstory.append(`<div class='hr_${time}'></div><div class='hr_${time}'></div><div class='hr_${time}'></div><div class='hr_${time}'></div><div class='hr_${time}'></div><div class='hr_${time}'></div><div class='hr_${time}'></div><div class='hr_${time}'></div>`)
					let hr_dashed = $(`.hr_${time}`),
						hr_top = h/3,
						hr_left = w/3,
						hrStyle = {
							position: "absolute"
						},
						crosswiseStyle = {
							width: "100%",
							height: 0,
							'border-bottom': "1px solid #fff",
							'border-style': "none none dashed none",
							left: 0
						},
						verticalStyle = {
							width: 0,
							height: "100%",
							'border-right': "1px solid #fff",
							'border-style': "none dashed none none",
							top: 0,
						}
					hr_dashed.css(hrStyle)
					$(hr_dashed[0]).css($.extend(crosswiseStyle, {top: 0}))
					$(hr_dashed[1]).css($.extend(crosswiseStyle, {top: hr_top}))
					$(hr_dashed[2]).css($.extend(crosswiseStyle, {top: hr_top*2}))
					$(hr_dashed[3]).css($.extend(crosswiseStyle, {top: h - 1}))
					$(hr_dashed[4]).css($.extend(verticalStyle, {left: 0}))
					$(hr_dashed[5]).css($.extend(verticalStyle, {left: hr_left}))
					$(hr_dashed[6]).css($.extend(verticalStyle, {left: hr_left*2}))
					$(hr_dashed[7]).css($.extend(verticalStyle, {left: w - 1}))
					bindImgDrag()
				},
				bindImgDrag = () => {
					let deltaX = 0,
						deltaY = 0,
						ol = overstory.offset().left,
						ot = overstory.offset().top,
						_img_ol = _img.offset().left,
						_img_ot = _img.offset().top,
						start = (e) => {
							_img_ol = _img.offset().left,
							_img_ot = _img.offset().top,
							deltaX = e.pageX - _img_ol + ol,
							deltaY = e.pageY - _img_ot + ot
							overstory.bind({
								'mousemove': move,
								'mouseup': stop
							})
							return false
						},
						_imgDragX = 0,
						_imgDragY = 0,
						move = (e) => {
							_img_info.n_x = e.pageX - deltaX,
							_img_info.n_y = e.pageY - deltaY,
							_imgDragX = (showW - _img_info.width)*imgZoom,
							_imgDragY = (showH - _img_info.height)*imgZoom
							if(_img_info.n_x > 0) {
								_img_info.n_x = 0
							}
							if(_img_info.n_x < _imgDragX) {
								_img_info.n_x = _imgDragX
							}
							if(_img_info.n_y > 0) {
								_img_info.n_y = 0
							}
							if(_img_info.n_y < _imgDragY) {
								_img_info.n_y = _imgDragY
							}
							_img.css({
								"left": _img_info.n_x,
								"top": _img_info.n_y
							})
							drawImg()
							return false
						},
						stop = () => {
							overstory.unbind({
								'mousemove': move,
								'mouseup': stop
							})
						}
					overstory.bind('mousedown', start)
				},
				addOriginalDraw = (e) => {
					showDom.append(`<canvas style='display:none;' width='${_img_info.width}' height='${_img_info.height}' id='draw_area_${time}'></canvas>`)
					canvasId = `draw_area_${time}`
					let canvasJsDom = document.getElementById(`draw_area_${time}`),
					context = canvasJsDom.getContext('2d')
					context.drawImage(e, 0, 0)
				},
				drawImg = () => {
					let canvas = document.getElementById(canvasId),
						cot1 = canvas.getContext("2d"),
						drawData = cot1.getImageData(_img_info.n_x == undefined ? overstoryOffetShowDomX : -_img_info.n_x + overstoryOffetShowDomX, _img_info.n_y == undefined ? 50 : -_img_info.n_y + overstoryOffetShowDomY, showW - overstoryOffetShowDomX, showH - overstoryOffetShowDomY)
						cot2 = nowImg.canvasJsDom.getContext("2d")
						cot2.putImageData(drawData, 0, 0, 0, 0, w, h)
						files.base64 = nowImg.canvasJsDom.toDataURL()
						nowImg.dom.attr("src", files.base64)
				},
				domChange = () => {
					let jsdom = dom[0],
						f = jsdom.files[0],
						reader = new FileReader(),
						img = new Image(),
						oparates = operate.children(),
						bindOperate = () => {
							$(oparates[0]).unbind().click(() => {
								imgZoom = imgZoom - 0.1
								img.style.zoom = imgZoom
							})
							$(oparates[1]).unbind().click(() => {
								imgZoom = imgZoom + 0.1
								img.style.zoom = imgZoom
							})
						},
						imgStyle = {
							zoom: 1,
							position: "absolute",
							top: 0,
							left: 0
						},
						imgSet = (e) => {
							showDom.html(e)
							_img = $(e)
							_img_info.width =  _img.width()
							_img_info.height = _img.height()
							_img.css(imgStyle)
							addOriginalDraw(e)
							drawImg()
						}
					(() => {
						files.name = f.name
						let flag = false,
						tsfx = f.name.substring(f.name.lastIndexOf(".")+1)
						for(let i in e.suffix) {
							if(e.suffix[i] == tsfx) {
								flag = true
								break
							}
						}
						if(!flag) {
							alert("Unsupported file type. " + f.type)
							throw new Error("Unsupported file type. " + f.type)
						}
					})()
					reader.onload = function(e) {
						img.onload = function() {
							imgSet(img)
							addOverstory()
							bindOperate()
						}
						img.src = e.target.result
//						operate.show()
					}
					reader.readAsDataURL(f)
					showDom.css(showStyle)
				},
				on = () => {
					dom.on("change", domChange)
				},
				go = () => {
					e.cut.place == "bottom" ? nowImg.parentArea.css(nowImg.parentBottomStyle) : nowImg.parentArea.css(nowImg.parentRightStyle)
					on()
				}
			go()
		},
		get = (t) => {
			file.t = t == "png" ? t : "jpg"
			let binary = atob(files.base64.split(',')[1]),
				arr = []
			for(var i = 0; i < binary.length; i++) {
				arr.push(binary.charCodeAt(i))
			}
			files.file = new Blob([new Uint8Array(arr)], {type: t})
			return files
		},
		init = (e) => {
			let dp = {
				dom: '#imgfile',
				suffix: ["jpg", "png", "bmp", "gif", "jpeg"],
				cut: {
					width: 200,
					height: 200,
					place: "right"
				},
				show: {
					width: 300,
					height: 300
				}
			}
			$.extend(dp, e)
			if(dp.cut.width > dp.show.width) {
				throw new Error('The "width" in the parameter cannot be greater than the "show.width"')
			}
			if(dp.cut.height > dp.show.height) {
				throw new Error('The "height" in the parameter cannot be greater than the "show.height"')
			}
			cutoutimg(dp)
		}
		return {
			init: init,
			get: get
		}
	})()
	return {
		imageCut: imageCut
	}
}));

使用说明

let imageCut = TraceImg.imageCut;
		步骤1: 初始化
		/**
		 * 支持参数
		 * {
		 * 		dom: "String",//字符串,input框的id或者class,默认为"#imgfile",
		 *		suffix: [],//数组,支持的图片格式,默认为["jpg", "png", "bmp", "gif", "jpeg"]【注意】:添加此属性会覆盖默认的属性,需要自行添加时请务必写全
		 * 		cut: {
		 * 			width: Number,//需要截取区域的宽,必须小于原始区域宽,默认为200
		 * 			height: Number,//需要截取区域的高,必须小于原始区域高,默认为200
		 * 			place: "String"//值为"bottom"或者"right",默认为right
		 * 		},
		 * 		show: {//原始图片显示区域的属性
		 * 			width: Number,//区域宽度,默认为300
		 * 			height: Number//区域高度,默认为300
		 * 		},
		 * }
		 */
		imageCut.init({
			dom: '#imgfile'
		});
		步骤2: 获取图片
		/**
		 * 获取file,在上传图片的时候调用
		 * imgType: "String"//值只支持"png"或者"jpg",默认为"jpg"
		 * @return {
		 * 	file://图片数据
		 * name://fileName
		 *	其余属性请用console.log()查看
		 * }
		 */
		imageCut.get(imgType)

测试dome: test.html

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<script src="js/jquery.min.js"></script>
    	<script src="js/trace.img.js"></script>
		<title></title>
	</head>
	<body>
		<div>
			<input type="file" id="imgfile"/>
		</div>
	</body>
	<script type="text/javascript">
		/**
		 * 支持参数
		 * {
		 * 		dom: "String",//字符串,input框的id或者class,默认为"#imgfile"
		 * 		cut: {
		 * 			width: Number,//需要截取区域的宽,必须小于原始区域宽,默认为200
		 * 			height: Number,//需要截取区域的高,必须小于原始区域高,默认为200
		 * 			place: "String"//值为"bottom"或者"right",默认为right
		 * 		},
		 * 		show: {//原始图片显示区域的属性
		 * 			width: Number,//区域宽度,默认为300
		 * 			height: Number//区域高度,默认为300
		 * 		},
		 * }
		 */
		TraceImg.imageCut.init({
			dom: '#imgfile',
			cut: {
				width: 160,
				height: 160,
				place: "right"
			},
			show: {
				width: 200,
				height: 200
			}
		});
		/**
		 * 获取file
		 * imgType: "String"//值只支持"png"或者"jpg",默认为"jpg"
		 * @return {
		 * 	file://图片数据
		 * name://fileName
		 * }
		 */
		TraceImg.imageCut.get(imgType)
	</script>
</html>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值