{"id":814,"date":"2025-09-15T18:21:54","date_gmt":"2025-09-15T18:21:54","guid":{"rendered":"https:\/\/laurisfilms.com\/?page_id=814"},"modified":"2025-09-15T18:51:18","modified_gmt":"2025-09-15T18:51:18","slug":"360-teste","status":"publish","type":"page","link":"https:\/\/laurisfilms.com\/","title":{"rendered":"360 Bandymas"},"content":{"rendered":"\n<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\" \/>\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\" \/>\n<title>360\u00b0 Spin Gallery (HTML)<\/title>\n\n<style>\n\/* --- Basic styles (edit as needed) --- *\/\nbody { font-family: system-ui, -apple-system, \"Segoe UI\", Roboto, Arial; padding:24px; background:#fafafa; color:#111; }\nh1 { font-size:20px; margin-bottom:12px; }\n\n.spin-gallery { position: relative; overflow: hidden; background: #fff; border:1px solid #e6e6e6; border-radius:8px; display:inline-block; margin:12px; }\n.spin-stage { width:100%; height:100%; display:flex; align-items:center; justify-content:center; cursor: grab; touch-action: pan-y; user-select:none; -webkit-user-select:none; }\n.spin-stage:active { cursor: grabbing; }\n.spin-image { max-width:100%; max-height:100%; display:block; pointer-events:none; user-select:none; }\n.spin-loader { position:absolute; left:12px; top:12px; padding:6px 10px; background: rgba(0,0,0,0.6); color:#fff; font-size:13px; border-radius:6px; z-index:20; }\n.spin-caption { position:absolute; right:12px; bottom:12px; padding:6px 8px; background: rgba(255,255,255,0.9); color:#111; font-size:13px; border-radius:6px; z-index:20; box-shadow:0 1px 4px rgba(0,0,0,0.06); }\n.controls { margin-top:10px; font-size:14px; color:#666; }\n.small { font-size:13px; color:#777; }\n.row { display:flex; gap:12px; flex-wrap:wrap; align-items:flex-start; }\n\n\/* quick responsive *\/\n@media (max-width:700px){ .spin-gallery { width:100% !important; } }\n<\/style>\n<\/head>\n<body>\n\n<h1>360\u00b0 Spin Gallery \u2014 Demo<\/h1>\n\n<div class=\"row\">\n  <!-- Gallery 1 -->\n  <div class=\"spin-gallery\" style=\"width:480px;height:320px\"\n       data-folder=\"http:\/\/laurisfilms.com\/wp-content\/uploads\/2025\/09\"\n       data-prefix=\"Frame-\"\n       data-count=\"8\"\n       data-ext=\"jpg\"\n       data-padding=\"2\"\n       data-autoplay=\"false\"\n       data-speed=\"80\">\n    <div class=\"spin-stage\" role=\"img\" aria-label=\"360 viewer\"><\/div>\n    <div class=\"spin-loader\">Loading&#8230;<\/div>\n    <div class=\"spin-caption small\">Drag to rotate<\/div>\n  <\/div>\n\n  <!-- Gallery 2 (example autoplay) -->\n  <div class=\"spin-gallery\" style=\"width:360px;height:260px\"\n       data-folder=\"http:\/\/laurisfilms.com\/wp-content\/uploads\/2025\/09\"\n       data-prefix=\"Frame-\"\n       data-count=\"8\"\n       data-ext=\"jpg\"\n       data-padding=\"2\"\n       data-autoplay=\"true\"\n       data-speed=\"120\">\n    <div class=\"spin-stage\" role=\"img\" aria-label=\"360 viewer\"><\/div>\n    <div class=\"spin-loader\">Loading&#8230;<\/div>\n    <div class=\"spin-caption small\">Tap to toggle autoplay<\/div>\n  <\/div>\n<\/div>\n\n<div class=\"controls\">\n  <div class=\"small\">Tip: use 24\u201336 frames (01..24 or 01..36). For best performance use WebP and a CDN if possible.<\/div>\n<\/div>\n\n<script>\n\/* Self-contained 360 viewer JS *\/\n(function () {\n  'use strict';\n\n  function pad(n, size) {\n    var s = String(n);\n    while (s.length < size) s = '0' + s;\n    return s;\n  }\n\n  function frameUrl(folder, prefix, idx, padding, ext) {\n    return folder + '\/' + prefix + pad(idx, padding) + '.' + ext;\n  }\n\n  function SpinViewer(root) {\n    this.root = root;\n    this.stage = root.querySelector('.spin-stage');\n    this.loader = root.querySelector('.spin-loader');\n    this.folder = root.getAttribute('data-folder') || '';\n    this.prefix = root.getAttribute('data-prefix') || 'frame-';\n    this.count = parseInt(root.getAttribute('data-count') || '36', 10);\n    this.ext = root.getAttribute('data-ext') || 'jpg';\n    this.padding = parseInt(root.getAttribute('data-padding') || '2', 10);\n    this.autoplay = root.getAttribute('data-autoplay') === 'true';\n    this.speed = parseInt(root.getAttribute('data-speed') || '80', 10);\n\n    this.current = 1;\n    this.images = new Array(this.count + 1);\n    this.preloaded = 0;\n    this.isDragging = false;\n    this.startX = 0;\n    this.sensitivity = Math.max(4, Math.floor((this.stage.clientWidth || 400) \/ (this.count * 1.5)));\n    this.autoplayId = null;\n\n    this._createImg();\n    this._bind();\n    this._preload();\n  }\n\n  SpinViewer.prototype._createImg = function () {\n    this.img = document.createElement('img');\n    this.img.className = 'spin-image';\n    this.img.alt = '360 view';\n    this.img.draggable = false;\n    this.img.style.userSelect = 'none';\n    this.stage.appendChild(this.img);\n  };\n\n  SpinViewer.prototype._preload = function () {\n    var self = this;\n    if (!this.folder) {\n      this.loader.textContent = 'No folder set';\n      return;\n    }\n    \/\/ preload frames\n    for (let i = 1; i <= this.count; i++) {\n      const url = frameUrl(self.folder, self.prefix, i, self.padding, self.ext);\n      const img = new Image();\n      img.onload = function () {\n        self.preloaded++;\n        self.images[i] = img;\n        if (self.preloaded === 1) self._show(self.current);\n        if (self.preloaded >= Math.min(6, self.count)) self.loader.style.display = 'none';\n      };\n      img.onerror = function () {\n        self.preloaded++;\n        self.images[i] = null;\n      };\n      img.src = url;\n    }\n  };\n\n  SpinViewer.prototype._show = function (idx) {\n    idx = ((idx - 1 + this.count) % this.count) + 1; \/\/ wrap 1..count\n    this.current = idx;\n    var pre = this.images[idx];\n    if (pre && pre.src) this.img.src = pre.src;\n    else this.img.src = frameUrl(this.folder, this.prefix, idx, this.padding, this.ext);\n  };\n\n  SpinViewer.prototype._bind = function () {\n    var self = this;\n\n    \/\/ mouse events\n    this.stage.addEventListener('mousedown', function (e) {\n      e.preventDefault();\n      self.isDragging = true;\n      self.startX = e.clientX;\n      if (self.autoplay) self._stopAutoplay();\n    });\n    window.addEventListener('mouseup', function () {\n      self.isDragging = false;\n    });\n    window.addEventListener('mousemove', function (e) {\n      if (!self.isDragging) return;\n      e.preventDefault();\n      self._dragTo(e.clientX);\n    });\n\n    \/\/ touch events\n    this.stage.addEventListener('touchstart', function (e) {\n      self.isDragging = true;\n      self.startX = e.touches[0].clientX;\n      if (self.autoplay) self._stopAutoplay();\n    }, { passive: true });\n    window.addEventListener('touchend', function () {\n      self.isDragging = false;\n    });\n    window.addEventListener('touchmove', function (e) {\n      if (!self.isDragging) return;\n      self._dragTo(e.touches[0].clientX);\n    }, { passive: true });\n\n    \/\/ click toggles autoplay if enabled\n    if (this.autoplay) {\n      this.stage.addEventListener('click', function () {\n        if (self.autoplayId) self._stopAutoplay();\n        else self._startAutoplay();\n      });\n      this._startAutoplay();\n    }\n\n    \/\/ responsive sensitivity\n    window.addEventListener('resize', function () {\n      self.sensitivity = Math.max(4, Math.floor(self.stage.clientWidth \/ (self.count * 1.5)));\n    });\n  };\n\n  \/\/ \ud83d\udd04 FIXED: reversed spin direction\n  SpinViewer.prototype._dragTo = function (x) {\n    var delta = x - this.startX;\n    if (Math.abs(delta) < this.sensitivity) return;\n    var frames = Math.floor(Math.abs(delta) \/ this.sensitivity);\n    if (delta > 0) this._show(this.current + frames); \/\/ reversed\n    else this._show(this.current - frames);           \/\/ reversed\n    this.startX = x;\n  };\n\n  \/\/ \ud83d\udd04 FIXED: autoplay direction reversed too\n  SpinViewer.prototype._startAutoplay = function () {\n    var self = this;\n    if (this.autoplayId) return;\n    this.autoplayId = setInterval(function () {\n      self._show(self.current - 1); \/\/ reversed autoplay\n    }, this.speed);\n  };\n\n  SpinViewer.prototype._stopAutoplay = function () {\n    if (this.autoplayId) {\n      clearInterval(this.autoplayId);\n      this.autoplayId = null;\n    }\n  };\n\n  \/\/ init all viewers on DOM ready\n  function init() {\n    var nodes = document.querySelectorAll('.spin-gallery');\n    nodes.forEach(function (n) {\n      if (!n._spin) n._spin = new SpinViewer(n);\n    });\n  }\n\n  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);\n  else init();\n\n})();\n<\/script>\n\n<\/body>\n<\/html>\n\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>360\u00b0 Spin Gallery (HTML) 360\u00b0 Spin Gallery \u2014 Demo Loading&#8230; Drag to rotate Loading&#8230; Tap to toggle autoplay Tip: use 24\u201336 frames (01..24 or 01..36). For best performance use WebP and a CDN if possible.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_uag_custom_page_level_css":"","_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"class_list":["post-814","page","type-page","status-publish","hentry"],"aioseo_notices":[],"uagb_featured_image_src":{"full":false,"thumbnail":false,"medium":false,"medium_large":false,"large":false,"1536x1536":false,"2048x2048":false,"woocommerce_thumbnail":false,"woocommerce_single":false,"woocommerce_gallery_thumbnail":false,"shop_catalog":false,"shop_single":false,"shop_thumbnail":false},"uagb_author_info":{"display_name":"lasabaliauskas@gmail.com","author_link":"https:\/\/laurisfilms.com\/index.php\/author\/lasabaliauskasgmail-com\/"},"uagb_comment_info":0,"uagb_excerpt":"360\u00b0 Spin Gallery (HTML) 360\u00b0 Spin Gallery \u2014 Demo Loading&#8230; Drag to rotate Loading&#8230; Tap to toggle autoplay Tip: use 24\u201336 frames (01..24 or 01..36). For best performance use WebP and a CDN if possible.","_links":{"self":[{"href":"https:\/\/laurisfilms.com\/index.php\/wp-json\/wp\/v2\/pages\/814","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/laurisfilms.com\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/laurisfilms.com\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/laurisfilms.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/laurisfilms.com\/index.php\/wp-json\/wp\/v2\/comments?post=814"}],"version-history":[{"count":3,"href":"https:\/\/laurisfilms.com\/index.php\/wp-json\/wp\/v2\/pages\/814\/revisions"}],"predecessor-version":[{"id":830,"href":"https:\/\/laurisfilms.com\/index.php\/wp-json\/wp\/v2\/pages\/814\/revisions\/830"}],"wp:attachment":[{"href":"https:\/\/laurisfilms.com\/index.php\/wp-json\/wp\/v2\/media?parent=814"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}