diff options
| -rw-r--r-- | archetypes/default.md | 10 | ||||
| -rw-r--r-- | assets/sass/main.scss | 24 | ||||
| -rw-r--r-- | assets/zoomjs/zoom.css | 41 | ||||
| -rwxr-xr-x | assets/zoomjs/zoom.js | 285 | ||||
| -rw-r--r-- | exampleSite/content/posts/image-zoom.md | 18 | ||||
| -rw-r--r-- | layouts/_default/_markup/render-image.html | 10 | ||||
| -rw-r--r-- | layouts/_default/baseof.html | 6 | ||||
| -rw-r--r-- | layouts/_default/single.html | 1 | ||||
| -rw-r--r-- | layouts/partials/footer.html | 4 |
9 files changed, 391 insertions, 8 deletions
diff --git a/archetypes/default.md b/archetypes/default.md index 079bb15..826319f 100644 --- a/archetypes/default.md +++ b/archetypes/default.md @@ -1,9 +1,9 @@ +++ -title: "{{ replace .Name "-" " " | title }}" -date: {{ .Date }} -draft: true -header_img: "" -short: false +title = "{{ replace .Name "-" " " | title }}" +date = {{ .Date }} +draft = true +header_img = "" +short = false toc = true tags = [] categories = [] diff --git a/assets/sass/main.scss b/assets/sass/main.scss index 9eff6c8..3f986db 100644 --- a/assets/sass/main.scss +++ b/assets/sass/main.scss @@ -303,6 +303,30 @@ samp { left: -0.75em; } } + + figure { + margin: .5rem; + text-align: center; + + .image-caption:not(:empty) { + min-width: 20%; + max-width: 80%; + display: inline-block; + font-style: italic; + padding: .5rem; + margin: 0 auto; + font-size: 13px; + color: $brand-gray; + } + + img { + display: block; + width: 100%; + height: auto; + margin: 0 auto; + overflow: hidden; + } + } } // Navigation diff --git a/assets/zoomjs/zoom.css b/assets/zoomjs/zoom.css new file mode 100644 index 0000000..679bccc --- /dev/null +++ b/assets/zoomjs/zoom.css @@ -0,0 +1,41 @@ +img[data-action="zoom"] { + cursor: pointer; + cursor: -webkit-zoom-in; + cursor: -moz-zoom-in; +} +.zoom-img, +.zoom-img-wrap { + position: relative; + z-index: 666; + -webkit-transition: all 300ms; + -o-transition: all 300ms; + transition: all 300ms; +} +img.zoom-img { + cursor: pointer; + cursor: -webkit-zoom-out; + cursor: -moz-zoom-out; +} +.zoom-overlay { + z-index: 420; + background: #fff; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + pointer-events: none; + filter: "alpha(opacity=0)"; + opacity: 0; + -webkit-transition: opacity 300ms; + -o-transition: opacity 300ms; + transition: opacity 300ms; +} +.zoom-overlay-open .zoom-overlay { + filter: "alpha(opacity=100)"; + opacity: 1; +} +.zoom-overlay-open, +.zoom-overlay-transitioning { + cursor: default; +} diff --git a/assets/zoomjs/zoom.js b/assets/zoomjs/zoom.js new file mode 100755 index 0000000..25d76d6 --- /dev/null +++ b/assets/zoomjs/zoom.js @@ -0,0 +1,285 @@ +/** + * zoom.js - It's the best way to zoom an image + * @version v0.0.2 + * @link https://github.com/fat/zoom.js + * @license MIT + */ + ++function ($) { "use strict"; + + /** + * The zoom service + */ + function ZoomService () { + this._activeZoom = + this._initialScrollPosition = + this._initialTouchPosition = + this._touchMoveListener = null + + this._$document = $(document) + this._$window = $(window) + this._$body = $(document.body) + + this._boundClick = $.proxy(this._clickHandler, this) + } + + ZoomService.prototype.listen = function () { + this._$body.on('click', '[data-action="zoom"]', $.proxy(this._zoom, this)) + } + + ZoomService.prototype._zoom = function (e) { + var target = e.target + + if (!target || target.tagName != 'IMG') return + + if (this._$body.hasClass('zoom-overlay-open')) return + + if (e.metaKey || e.ctrlKey) { + return window.open((e.target.getAttribute('data-original') || e.target.src), '_blank') + } + + if (target.width >= ($(window).width() - Zoom.OFFSET)) return + + this._activeZoomClose(true) + + this._activeZoom = new Zoom(target) + this._activeZoom.zoomImage() + + // todo(fat): probably worth throttling this + this._$window.on('scroll.zoom', $.proxy(this._scrollHandler, this)) + + this._$document.on('keyup.zoom', $.proxy(this._keyHandler, this)) + this._$document.on('touchstart.zoom', $.proxy(this._touchStart, this)) + + // we use a capturing phase here to prevent unintended js events + // sadly no useCapture in jquery api (http://bugs.jquery.com/ticket/14953) + if (document.addEventListener) { + document.addEventListener('click', this._boundClick, true) + } else { + document.attachEvent('onclick', this._boundClick, true) + } + + if ('bubbles' in e) { + if (e.bubbles) e.stopPropagation() + } else { + // Internet Explorer before version 9 + e.cancelBubble = true + } + } + + ZoomService.prototype._activeZoomClose = function (forceDispose) { + if (!this._activeZoom) return + + if (forceDispose) { + this._activeZoom.dispose() + } else { + this._activeZoom.close() + } + + this._$window.off('.zoom') + this._$document.off('.zoom') + + document.removeEventListener('click', this._boundClick, true) + + this._activeZoom = null + } + + ZoomService.prototype._scrollHandler = function (e) { + if (this._initialScrollPosition === null) this._initialScrollPosition = $(window).scrollTop() + var deltaY = this._initialScrollPosition - $(window).scrollTop() + if (Math.abs(deltaY) >= 40) this._activeZoomClose() + } + + ZoomService.prototype._keyHandler = function (e) { + if (e.keyCode == 27) this._activeZoomClose() + } + + ZoomService.prototype._clickHandler = function (e) { + if (e.preventDefault) e.preventDefault() + else event.returnValue = false + + if ('bubbles' in e) { + if (e.bubbles) e.stopPropagation() + } else { + // Internet Explorer before version 9 + e.cancelBubble = true + } + + this._activeZoomClose() + } + + ZoomService.prototype._touchStart = function (e) { + this._initialTouchPosition = e.touches[0].pageY + $(e.target).on('touchmove.zoom', $.proxy(this._touchMove, this)) + } + + ZoomService.prototype._touchMove = function (e) { + if (Math.abs(e.touches[0].pageY - this._initialTouchPosition) > 10) { + this._activeZoomClose() + $(e.target).off('touchmove.zoom') + } + } + + + /** + * The zoom object + */ + function Zoom (img) { + this._fullHeight = + this._fullWidth = + this._overlay = + this._targetImageWrap = null + + this._targetImage = img + + this._$body = $(document.body) + } + + Zoom.OFFSET = 80 + Zoom._MAX_WIDTH = 2560 + Zoom._MAX_HEIGHT = 4096 + + Zoom.prototype.zoomImage = function () { + var img = document.createElement('img') + img.onload = $.proxy(function () { + this._fullHeight = Number(img.height) + this._fullWidth = Number(img.width) + this._zoomOriginal() + }, this) + img.src = this._targetImage.src + } + + Zoom.prototype._zoomOriginal = function () { + this._targetImageWrap = document.createElement('div') + this._targetImageWrap.className = 'zoom-img-wrap' + + this._targetImage.parentNode.insertBefore(this._targetImageWrap, this._targetImage) + this._targetImageWrap.appendChild(this._targetImage) + + $(this._targetImage) + .addClass('zoom-img') + .attr('data-action', 'zoom-out') + + this._overlay = document.createElement('div') + this._overlay.className = 'zoom-overlay' + + document.body.appendChild(this._overlay) + + this._calculateZoom() + this._triggerAnimation() + } + + Zoom.prototype._calculateZoom = function () { + this._targetImage.offsetWidth // repaint before animating + + var originalFullImageWidth = this._fullWidth + var originalFullImageHeight = this._fullHeight + + var scrollTop = $(window).scrollTop() + + var maxScaleFactor = originalFullImageWidth / this._targetImage.width + + var viewportHeight = ($(window).height() - Zoom.OFFSET) + var viewportWidth = ($(window).width() - Zoom.OFFSET) + + var imageAspectRatio = originalFullImageWidth / originalFullImageHeight + var viewportAspectRatio = viewportWidth / viewportHeight + + if (originalFullImageWidth < viewportWidth && originalFullImageHeight < viewportHeight) { + this._imgScaleFactor = maxScaleFactor + + } else if (imageAspectRatio < viewportAspectRatio) { + this._imgScaleFactor = (viewportHeight / originalFullImageHeight) * maxScaleFactor + + } else { + this._imgScaleFactor = (viewportWidth / originalFullImageWidth) * maxScaleFactor + } + } + + Zoom.prototype._triggerAnimation = function () { + this._targetImage.offsetWidth // repaint before animating + + var imageOffset = $(this._targetImage).offset() + var scrollTop = $(window).scrollTop() + + var viewportY = scrollTop + ($(window).height() / 2) + var viewportX = ($(window).width() / 2) + + var imageCenterY = imageOffset.top + (this._targetImage.height / 2) + var imageCenterX = imageOffset.left + (this._targetImage.width / 2) + + this._translateY = viewportY - imageCenterY + this._translateX = viewportX - imageCenterX + + var targetTransform = 'scale(' + this._imgScaleFactor + ')' + var imageWrapTransform = 'translate(' + this._translateX + 'px, ' + this._translateY + 'px)' + + if ($.support.transition) { + imageWrapTransform += ' translateZ(0)' + } + + $(this._targetImage) + .css({ + '-webkit-transform': targetTransform, + '-ms-transform': targetTransform, + 'transform': targetTransform + }) + + $(this._targetImageWrap) + .css({ + '-webkit-transform': imageWrapTransform, + '-ms-transform': imageWrapTransform, + 'transform': imageWrapTransform + }) + + this._$body.addClass('zoom-overlay-open') + } + + Zoom.prototype.close = function () { + this._$body + .removeClass('zoom-overlay-open') + .addClass('zoom-overlay-transitioning') + + // we use setStyle here so that the correct vender prefix for transform is used + $(this._targetImage) + .css({ + '-webkit-transform': '', + '-ms-transform': '', + 'transform': '' + }) + + $(this._targetImageWrap) + .css({ + '-webkit-transform': '', + '-ms-transform': '', + 'transform': '' + }) + + if (!$.support.transition) { + return this.dispose() + } + + $(this._targetImage) + .one($.support.transition.end, $.proxy(this.dispose, this)) + .emulateTransitionEnd(300) + } + + Zoom.prototype.dispose = function () { + if (this._targetImageWrap && this._targetImageWrap.parentNode) { + $(this._targetImage) + .removeClass('zoom-img') + .attr('data-action', 'zoom') + + this._targetImageWrap.parentNode.replaceChild(this._targetImage, this._targetImageWrap) + this._overlay.parentNode.removeChild(this._overlay) + + this._$body.removeClass('zoom-overlay-transitioning') + } + } + + // wait for dom ready (incase script included before body) + $(function () { + new ZoomService().listen() + }) + +}(jQuery) diff --git a/exampleSite/content/posts/image-zoom.md b/exampleSite/content/posts/image-zoom.md new file mode 100644 index 0000000..a206e07 --- /dev/null +++ b/exampleSite/content/posts/image-zoom.md @@ -0,0 +1,18 @@ ++++ +title = "Image Zoom" +date = 2022-07-29T14:07:47+08:00 +header_img = "" +short = false +toc = true +tags = ["theme", "image zoom"] +categories = [] ++++ + +## Image Zoom + +[zoom.js](https://github.com/fat/zoom.js) is a simple jQuery plugin for image zooming. + + + + + diff --git a/layouts/_default/_markup/render-image.html b/layouts/_default/_markup/render-image.html new file mode 100644 index 0000000..f4f9389 --- /dev/null +++ b/layouts/_default/_markup/render-image.html @@ -0,0 +1,10 @@ +<figure> + <a class="paragraph-image"> + <img src="{{ .Destination | safeURL }}" data-action="zoom" alt="{{ .Text }}" {{ with .Title }} title="{{ . }}"{{ end }} loading="lazy" decoding="async"> + </a> + {{ with .Title }} + <figcaption class="image-caption"> + {{- . | safeHTML -}} + </figcaption> + {{ end }} +</figure>
\ No newline at end of file diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html index 3b18f33..a57646a 100644 --- a/layouts/_default/baseof.html +++ b/layouts/_default/baseof.html @@ -33,6 +33,10 @@ {{ $style := resources.Get "sass/main.scss" | resources.ToCSS $options }} <link rel="stylesheet" href="{{ $style.Permalink }}"> + {{ $zoom_css := resources.Get "zoomjs/zoom.css" | resources.Minify }} + <link rel="stylesheet" href="{{ $zoom_css.Permalink }}"> + + {{ range .Site.Params.custom_css -}} {{ $custom_template := resources.Get . }} {{ if $custom_template }} @@ -69,7 +73,7 @@ {{ .Scratch.Set "header_img" $header_img }} {{ end }} - {{ if and .IsPage (gt .WordCount 400 ) (.Params.toc) }} + {{ if and .IsPage (.Params.toc) }} {{ .Scratch.Set "toc" true }} {{ end }} diff --git a/layouts/_default/single.html b/layouts/_default/single.html index 54f3e8b..a16b66c 100644 --- a/layouts/_default/single.html +++ b/layouts/_default/single.html @@ -10,7 +10,6 @@ col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1 post-container"> - {{ .TableOfContents }} {{ .Content }} <hr style="visibility: hidden;" /> diff --git a/layouts/partials/footer.html b/layouts/partials/footer.html index e570d42..086d421 100644 --- a/layouts/partials/footer.html +++ b/layouts/partials/footer.html @@ -85,7 +85,6 @@ }); </script> - {{ end }} <!-- Simple Jekyll Search --> @@ -149,3 +148,6 @@ {{ if not .Site.IsServer }} {{ template "_internal/google_analytics.html" . }} {{ end }} + +{{ $zoom_js := resources.Get "zoomjs/zoom.js" | resources.Minify }} +<script src="{{ $zoom_js.RelPermalink }}"></script> |
