Greasy Fork

vanilla-js-wheel-zoom

Image resizing using mouse wheel + drag scrollable image (as well as any HTML content)

目前为 2021-01-29 提交的版本。查看 最新版本

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.greasyfork.icu/scripts/420842/895198/vanilla-js-wheel-zoom.js

// vanilla-js-wheel-zoom https://github.com/worka/vanilla-js-wheel-zoom
(function (a, b) { "object" == typeof exports && "undefined" != typeof module ? module.exports = b() : "function" == typeof define && define.amd ? define(b) : (a = a || self, a.WZoom = b()) })(this, function () { 'use strict'; var k = Math.abs; function a(a) { var b = a.getBoundingClientRect(), c = document, d = c.body, e = c.documentElement, f = window.pageYOffset || e.scrollTop || d.scrollTop, g = window.pageXOffset || e.scrollLeft || d.scrollLeft, h = e.clientTop || d.clientTop || 0, i = e.clientLeft || d.clientLeft || 0, j = b.top + f - h, k = b.left + g - i; return { top: j, left: k } } function b(a, b) { if (a && b) for (var c in b) b.hasOwnProperty(c) && (a[c] = b[c]); return a } function c(a, b, c) { var d = !!(3 < arguments.length && void 0 !== arguments[3]) && arguments[3]; a.addEventListener(b, c, d) } function d(a, b, c) { var d = !!(3 < arguments.length && void 0 !== arguments[3]) && arguments[3]; a.removeEventListener(b, c, d) } function e() { return "ontouchstart" in window || 0 < navigator.MaxTouchPoints || 0 < navigator.msMaxTouchPoints } function f(a) { return "wheel" === a.type || "mousedown" === a.type || "mousemove" === a.type || "mouseup" === a.type ? a.clientX : a.changedTouches[0].clientX } function g(a) { return "wheel" === a.type || "mousedown" === a.type || "mousemove" === a.type || "mouseup" === a.type ? a.clientY : a.changedTouches[0].clientY } function h(a, d) { var f = this, g = 2 < arguments.length && void 0 !== arguments[2] ? arguments[2] : {}; this._dropHandler = this._dropHandler.bind(this), this._grabHandler = this._grabHandler.bind(this), this._moveHandler = this._moveHandler.bind(this), this.options = b({ smoothExtinction: !1, onGrab: null, onMove: null, onDrop: null }, g), this.isTouch = e(), this.events = this.isTouch ? { grab: "touchstart", move: "touchmove", drop: "touchend" } : { grab: "mousedown", move: "mousemove", drop: "mouseup" }, this.events.options = !!this.isTouch && { passive: !0 }, this.window = a, this.content = d, c(this.content.$element, this.events.grab, function (a) { (f.isTouch && 1 === a.touches.length || 1 === a.buttons) && f._grabHandler(a) }, this.events.options) } function i(a, b) { var c = b.left, d = b.top, e = b.scale; a.style.transform = "translate3d(".concat(c, "px, ").concat(d, "px, 0px) scale(").concat(e, ")") } function j(a) { var c = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : {}; this._init = this._init.bind(this), this._prepare = this._prepare.bind(this), this._computeNewScale = this._computeNewScale.bind(this), this._computeNewPosition = this._computeNewPosition.bind(this), this._transform = this._transform.bind(this); this.content.$element = document.querySelector(a), this.isTouch = e(), this.events = this.isTouch ? { down: "touchstart", up: "touchend" } : { down: "mousedown", up: "mouseup" }, this.events.options = !!this.isTouch && { passive: !0 }, this.content.$element && (this.options = b({ type: "image", width: null, height: null, dragScrollable: !0, dragScrollableOptions: {}, maxScale: 1, speed: 50 }, c), this.window.$element = this.content.$element.parentNode, "image" === this.options.type ? this.content.$element.complete ? this._init() : this.content.$element.onload = this._init : this._init()) } return h.prototype = { constructor: h, window: null, content: null, isTouch: !1, isGrab: !1, events: null, moveTimer: null, options: {}, coordinates: null, speed: null, _grabHandler: function (a) { this.isTouch || a.preventDefault(), this.isGrab = !0, this.coordinates = { left: f(a), top: g(a) }, this.speed = { x: 0, y: 0 }, c(document, this.events.drop, this._dropHandler, this.events.options), c(document, this.events.move, this._moveHandler, this.events.options), "function" == typeof this.options.onGrab && this.options.onGrab() }, _dropHandler: function (a) { this.isTouch || a.preventDefault(), this.isGrab = !1, d(document, this.events.drop, this._dropHandler), d(document, this.events.move, this._moveHandler), "function" == typeof this.options.onDrop && this.options.onDrop() }, _moveHandler: function (a) { this.isTouch || a.preventDefault(); var b = this.window, c = this.content, d = this.speed, e = this.coordinates, h = this.options; d.x = f(a) - e.left, d.y = g(a) - e.top, clearTimeout(this.moveTimer), this.moveTimer = setTimeout(function () { d.x = 0, d.y = 0 }, 50); var j = c.currentLeft + d.x, l = c.currentTop + d.y, m = (c.currentWidth - b.originalWidth) / 2 + c.correctX, n = (c.currentHeight - b.originalHeight) / 2 + c.correctY; k(j) <= m && (c.currentLeft = j), k(l) <= n && (c.currentTop = l), i(c.$element, { left: c.currentLeft, top: c.currentTop, scale: c.currentScale }), e.left = f(a), e.top = g(a), "function" == typeof h.onMove && h.onMove() } }, j.prototype = { constructor: j, isTouch: !1, events: null, content: {}, window: {}, direction: 1, options: null, stack: [], _init: function () { var a = this; this._prepare(), !0 === this.options.dragScrollable && new h(this.window, this.content, this.options.dragScrollableOptions), c(this.window.$element, "wheel", function (b) { b.preventDefault(), a._transform(a._computeNewPosition(a._computeNewScale(b.deltaY), { x: f(b), y: g(b) })) }); var b = !0; c(this.window.$element, this.events.down, function (c) { (a.isTouch && 1 === c.touches.length || 1 === c.buttons) && (b = !1, setTimeout(function () { return b = !0 }, 150)) }, this.events.options), c(this.window.$element, this.events.up, function (c) { b || (a._transform(a._computeNewPosition(1 === a.direction ? a.content.maxScale : a.content.minScale, { x: f(c), y: g(c) })), a.direction *= -1) }, this.events.options) }, _prepare: function () { var b = Math.max, c = Math.min, d = a(this.window.$element); this.window.originalWidth = this.window.$element.offsetWidth, this.window.originalHeight = this.window.$element.offsetHeight, this.window.positionLeft = d.left, this.window.positionTop = d.top, "image" === this.options.type ? (this.content.originalWidth = this.options.width || this.content.$element.naturalWidth, this.content.originalHeight = this.options.height || this.content.$element.naturalHeight) : (this.content.originalWidth = this.options.width || this.content.$element.offsetWidth, this.content.originalHeight = this.options.height || this.content.$element.offsetHeight), this.content.minScale = c(this.window.originalWidth / this.content.originalWidth, this.window.originalHeight / this.content.originalHeight), this.content.maxScale = this.options.maxScale, this.content.currentWidth = this.content.originalWidth * this.content.minScale, this.content.currentHeight = this.content.originalHeight * this.content.minScale, this.content.currentLeft = 0, this.content.currentTop = 0, this.content.currentScale = this.content.minScale, this.content.correctX = b(0, (this.window.originalWidth - this.content.currentWidth) / 2), this.content.correctY = b(0, (this.window.originalHeight - this.content.currentHeight) / 2), this.content.$element.style.transform = "translate3d(0px, 0px, 0px) scale(".concat(this.content.minScale, ")"), "function" == typeof this.options.prepare && this.options.prepare() }, _computeNewScale: function (a) { this.direction = 0 > a ? 1 : -1; var b = this.content, c = b.minScale, d = b.maxScale, e = b.currentScale, f = e + this.direction / this.options.speed; return f < c ? c : f > d ? d : f }, _computeNewPosition: function (a, b) { var c = b.x, d = b.y, e = this.window, f = this.content, g = f.originalWidth * a, h = f.originalHeight * a, i = document, j = i.body, l = i.documentElement, m = e.pageXOffset || l.scrollLeft || j.scrollLeft, n = e.pageYOffset || l.scrollTop || j.scrollTop, o = c + m - e.positionLeft, p = e.originalWidth / 2 - o, q = p + f.currentLeft, r = q * (g / f.currentWidth) - q + f.currentLeft; if (-1 === this.direction && (g - e.originalWidth) / 2 + f.correctX < k(r)) { var s = 0 > r ? -1 : 1; r = ((g - e.originalWidth) / 2 + f.correctX) * s } var t = d + n - e.positionTop, u = e.originalHeight / 2 - t, v = u + f.currentTop, w = v * (h / f.currentHeight) - v + f.currentTop; if (-1 === this.direction && (h - e.originalHeight) / 2 + f.correctY < k(w)) { var x = 0 > w ? -1 : 1; w = ((h - e.originalHeight) / 2 + f.correctY) * x } a === this.content.minScale && (r = w = 0); var y = { currentLeft: f.currentLeft, newLeft: r, currentTop: f.currentTop, newTop: w, currentScale: f.currentScale, newScale: a }; return f.currentWidth = g, f.currentHeight = h, f.currentLeft = r, f.currentTop = w, f.currentScale = a, y }, _transform: function (a) { var b = a.currentLeft, c = a.newLeft, d = a.currentTop, e = a.newTop, f = a.currentScale, g = a.newScale; this.content.$element.style.transform = "translate3d(".concat(c, "px, ").concat(e, "px, 0px) scale(").concat(g, ")"), "function" == typeof this.options.rescale && this.options.rescale() }, _zoom: function (b) { var c = a(this.window.$element); this._transform(this._computeNewPosition(this._computeNewScale(b), { x: c.left + this.window.originalWidth / 2, y: c.top + this.window.originalHeight / 2 })) }, prepare: function () { this._prepare() }, zoomUp: function () { this._zoom(-1) }, zoomDown: function () { this._zoom(1) } }, j.create = function (a, b) { return new j(a, b) }, j });