Home / Collections / Trade
Trade Range
128 Items

Filter

Clear all
Sort by:  Featured
Product Type
Colour
Lens Type
Price
$0.00
$143.99
$59.99 AUD

4.9 (11)

SELLING FAST! ✨
$69.99 AUD

4.5 (6)

$69.99 AUD

4.9 (2101)

$69.99 AUD

4.9 (884)

$69.99 AUD

4.9 (884)

$59.99 AUD

4.0 (4)

$59.99 AUD

4.9 (11)

$59.99 AUD

4.0 (4)

$39.99 AUD

4.9 (884)

VP Multi Coat + Anti Reflective
$76.00 AUD
UV Filter
$130.00 AUD

3.0 (1)

FULL CONTROL (BLUE LIGHT)
$134.00 AUD
SUPER HARD COAT
$0.00 AUD

4.5 (2)

$39.99 AUD

4.9 (773)

$69.99 AUD

4.9 (884)

$39.99 AUD

4.9 (773)

You've viewed 96 of 128 products

// Drop-in replacement: renders camera video INSIDE the same WebGL canvas as the 3D model (sticky composite). // Fixes: background quad writing depth (which would hide the model). // Notes: // - Keeps your UI/HTML/CSS and product logic basically identical. // - Uses MediaPipe Tasks Vision 0.10.32 with NAMED exports (no default export). // - Turns off blendshapes (you weren't using them) for free perf. // - Avoids resizing canvas every frame; only resizes when needed. import { FaceLandmarker, FilesetResolver } from "https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@0.10.32"; import * as THREE from "https://cdn.skypack.dev/three@0.129.0/build/three.module.js"; import { GLTFLoader } from "https://cdn.skypack.dev/three@0.129.0/examples/jsm/loaders/GLTFLoader.js"; import { DRACOLoader } from "https://cdn.skypack.dev/three@0.129.0/examples/jsm/loaders//DRACOLoader.js"; import { RoomEnvironment } from "https://cdn.skypack.dev/three@0.129.0/examples/jsm/environments/RoomEnvironment.js"; class SSTO { VIDEO_DEPTH = 500; FOV_DEGREES = 63; NEAR = 1; FAR = 10000; video = null; lastVideoTime = -1; constructor(product_index, ssto_config) { console.log("constructing"); this.product_index = product_index; this.ssto_config = ssto_config; const self = this; const css = `body.noscroll { overflow:hidden!important;position:fixed!important;} * {border-collapse: collapse; } .ssvto-container { z-index: 1000001; position: fixed; top: 0; left: 0;width: 100%;height: 100%;background-color: rgba(0, 0, 0, 0.5);display: flex;justify-content: center;align-items: center; } .ssvto-main { margin-left: 20px;margin-right: 20px;border-radius: 10px; align-items: start;position: relative;max-width: 1200px; max-height: 700px; height: 700px; background-color: white; display: flex; justify-content: start; flex-direction: row; } .ssvto-main.ssvto-accept { flex-direction: column; width: 100%; align-items: center; align-content: center; justify-content: center; } .ssvto-main.ssvto-app-init { flex-direction: column; width: 100%; align-items: center; align-content: center; justify-content: center; } .ssvto-accept-message { max-width: 700px; padding-top: 20px; padding-bottom: 20px; font-size: 16px; font-family: "chivo"; font-weight: 900; text-align: center; text-transform: uppercase; font-style: italic; } .ssvto-shield { width: 30px; } .ssvto-close-icon { z-index: 1000001;position: absolute; top: 14px; left: 13px; width: 12px; cursor: pointer; filter: invert(1);} .ssvto-range-title { text-transform: uppercase; font-style: italic; font-family: "swizzy"; font-weight: 900; text-align: left; padding-left: 40px; padding-top: 7px; padding-bottom: 8px; border-bottom: 2px solid #eee; } .ssvto-left { position: relative; width: 50%; display: flex; flex-direction: column; max-height: 700px; padding-bottom: 25px; } .ssvto-products { overflow-y: auto; width: 100%; } .ssvto-products-inner { display: flex; justify-content: start; align-items: start; flex-wrap: wrap; gap: 15px; padding: 20px 40px 20px 40px; } .ssvto-product { display: flex; min-width: 130px; flex: 1 1 0; max-width: 33%; flex-direction: column; align-items: center;} .ssvto-product img { border: 2px solid #eee; width: 100%; } .ssvto-product.selected img { border: 2px solid #000; } .ssvto-product-title { text-transform: uppercase;font-size: 12px;font-style: italic;font-family: "swizzy";font-weight: 900;text-align: center; padding: 5px; } .ssvto-video-container { position: relative; width: 50%; height: 100%; background-color: black; overflow: hidden; } .ssvto-video { width:100%; height:100%; object-fit: cover; } .ssvto-flip { transform: scaleX(-1); } .ssvto-canvas { height:100%; object-fit: cover; top: 0px; left: 0px; position: absolute; } .ssvto-mobile-product-prev,.ssvto-mobile-product-next { display: none; } .ssvto-selected-product-title { max-width: 220px; text-align: center; position: absolute; display: block; color: white; left: 50%; bottom: 50px; transform: translateX(-50%);letter-spacing: 2px; font-size: 14px; font-style: italic; font-family: "swizzy"; font-weight: 900; text-transform: uppercase;} .ssvto-add-to-cart-button { position: absolute; bottom: 10px; left: 50%; transform: translateX(-50%); } .ssvto-loader { display: none; background: rgba(0, 0, 0, 0.5);padding: 20px;border-radius: 10px;position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);z-index: 20000;width: 150px;height: 150px; } .ssvto-accept-button-set { display: flex; justify-content: center; align-items: center; gap: 15px; } .ssvto-button { border: 1px solid #000; background-color: #fff; color: #000; padding: 7px 15px; border-radius: 0px; font-size: 13px; text-transform: uppercase; font-family: "swizzy"; font-weight: 900; cursor: pointer; font-style: italic; } .ssvto-button.black { background-color: #000; color: #fff; } #ssvto-controls-button { width: 10px; height: 10px;position: absolute; top: 0px; right: 0px; background-color: #00000000; color: #fff; border: 0px solid #fff; padding: 5px; border-radius: 5px; cursor: pointer; } #ssvto-controls { position: absolute; top: 10px; right: 10px; display: none; flex-direction: column; gap: 5px; } #ssvto-controls input { padding: 5px; border: 1px solid #000; background: #fff; width: 75px; } .ssvvt-control-set { display: flex; gap: 5px; } .ssvvt-control-set button { width: 40px; text-align: center;font-size: 10px; font-family: swizzy; font-weight: 900; font-style: italic;text-transform: uppercase;border-radius: 5px; font-size: 12px; padding: 3px; border: 1px solid #fff; background-color: #000; color: #fff; cursor: pointer; } .ssvvt-control-set label {text-shadow: 1px 1px #fff; align-content: center; width: 100px; text-align: right; font-family: swizzy; font-weight: 900; text-transform: uppercase; font-style: italic; font-size: 12px; } @media screen and (orientation: portrait) { .ssvto-close-icon { filter: invert(0); width: 25px; top: 15px; left: 15px;} .ssvto-main { margin-left: 0px;margin-right: 0px;max-height: 100%; max-width: 100%; height: 100%; display: block; border-radius: 0px; width: 100%;} .ssvto-left { padding-bottom: 35px;position: absolute; bottom: 0px; width: 100%; height: 230px; z-index: 10;} .ssvto-video-container { width: 100%; } .ssvto-range-title { display: none; } .ssvto-products { width: 100%; overflow-y: hidden; } .ssvto-products-inner { transition: left 0.6s;display: flex; justify-content: start; align-items: center; flex-wrap: nowrap; gap: 22px; padding: 10px 35px 10px 35px; position: absolute; } .ssvto-product { max-width: 75px;min-width: 75px; width: 75px; transition: width 0.6s, max-width 0.6s, padding-bottom 0.6s; } .ssvto-product.selected { width: 130px; max-width: 130px; padding-bottom: 0px; } .ssvto-product img { border-width: 0px; border-radius: 10px; } .ssvto-product.selected img { border: 0px; } .ssvto-product-title { color: #fff; letter-spacing: 2px;} .ssvto-product .ssvto-product-title { display: none; } .ssvto-selected-product-title { max-width: 220px; text-align: center; position: absolute; display: block; color: white; left: 50%; bottom: 50px; transform: translateX(-50%);letter-spacing: 2px; font-size: 11px; font-style: italic; font-family: "chivo"; font-weight: 900; text-transform: uppercase;} .ssvto-add-to-cart-button { z-index: 1000; position: absolute; bottom: 7px; left: 50%; transform: translateX(-50%); } .ssvto-mobile-product-prev { z-index: 1000;display: block; width: 30px; height: 30px; position: absolute; bottom: 40px; left: 20px; cursor: pointer; } .ssvto-mobile-product-next { z-index: 1000;display: block; width: 30px; height: 30px; position: absolute; bottom: 40px; right: 20px; cursor: pointer; } .ssvto-accept-message { padding-left: 20px; padding-right: 20px; } .ssvto-app-init { padding: 20px; } }`; document.head.insertAdjacentHTML("beforeend", ``); const html = ` `; const dialog = document.createElement("div"); dialog.className = "ssvto-container"; dialog.innerHTML = html; document.body.appendChild(dialog); document.body.classList.add("noscroll"); document.querySelector(".ssvto-close-icon").onclick = function () { if (self.webcamRunning) self.webcamRunning = false; if (self.stream) self.stream.getTracks().forEach((track) => track.stop()); document.body.removeChild(dialog); document.body.classList.remove("noscroll"); }; this.video = document.querySelector(".ssvto-video"); this.canvas_element = document.querySelector(".ssvto-canvas"); this.loading = document.querySelector(".ssvto-loader"); for (let i = 0; i < ssto_config.products.length; i++) { const product = ssto_config.products[i]; const product_element = document.createElement("div"); product_element.className = "ssvto-product"; if (i === product_index) { product_element.classList.add("selected"); document.querySelector(".ssvto-selected-product-title").innerHTML = product.title; } product_element.innerHTML = `
${product.title}
`; product_element.addEventListener("click", () => { this.load_new_product(product_element); }); document.querySelector(".ssvto-products-inner").appendChild(product_element); } document.querySelector(".ssvto-mobile-product-prev").addEventListener("click", () => { this.prev(); }); document.querySelector(".ssvto-mobile-product-next").addEventListener("click", () => { this.next(); }); [...document.querySelectorAll(".ssvto-add-to-cart-button")].forEach((el) => el.addEventListener("click", async () => { const selected_product = document.querySelector(".ssvto-product.selected"); this.product_index = Array.from(selected_product.parentElement.children).indexOf(selected_product); const product_data = ssto_config.products[product_index]; if (ssto_config.on_add_to_cart) { this.loading.style.display = "flex"; await ssto_config.on_add_to_cart(product_data); this.loading.style.display = "none"; } }) ); window.addEventListener("resize", () => { this.handleResize(); this.adjustProductView(); }); window.addEventListener("orientationchange", () => { this.handleResize(); this.adjustProductView(); }); document.getElementById("ssvto-accept-button").onclick = function () { self.set_cookie("ssto_accept", "yes"); document.querySelector(".ssvto-accept").style.display = "none"; document.querySelector(".ssvto-app-init").style.display = "flex"; self.run_ssvto(); window.ss_ab?.("signal", { signal: "virtual-try-on-terms-accepted" }); }; document.getElementById("ssvto-decline-button").onclick = function () { self.set_cookie("ssto_accept", "no"); document.body.removeChild(dialog); document.body.classList.remove("noscroll"); window.ss_ab?.("signal", { signal: "virtual-try-on-terms-declined" }); }; document.getElementById("ssvto-init-cancel-button").onclick = function () { if (self.webcamRunning) self.webcamRunning = false; if (self.stream) self.stream.getTracks().forEach((track) => track.stop()); document.body.removeChild(dialog); document.body.classList.remove("noscroll"); }; if (this.get_cookie("ssto_accept") === "yes") { document.querySelector(".ssvto-accept").style.display = "none"; document.querySelector(".ssvto-app-init").style.display = "flex"; this.run_ssvto(); } else { document.querySelector(".ssvto-accept").style.display = "flex"; document.querySelector(".ssvto-app").style.display = "none"; } // touch events this.touchstartX = 0; this.touchendX = 0; this.canvas_element.addEventListener("touchstart", (e) => { this.touchstartX = e.changedTouches[0].screenX; }); this.canvas_element.addEventListener("touchend", (e) => { this.touchendX = e.changedTouches[0].screenX; this.checkDirection(e); }); // controls (unchanged) document.getElementById("sstvto-control-x-shift").addEventListener("change", (e) => { if (this.model_scene) this.model_scene.position.x = parseFloat(e.target.value); }); document.getElementById("sstvto-control-y-shift").addEventListener("change", (e) => { if (this.model_scene) this.model_scene.position.y = parseFloat(e.target.value); }); document.getElementById("sstvto-control-z-shift").addEventListener("change", (e) => { if (this.model_scene) this.model_scene.position.z = parseFloat(e.target.value); }); document.getElementById("sstvto-control-x-tilt").addEventListener("change", (e) => { if (this.model_scene) this.model_scene.rotation.x = parseFloat(e.target.value); }); document.getElementById("sstvto-control-scale").addEventListener("change", (e) => { if (this.model_scene) { const s = parseFloat(e.target.value); this.model_scene.scale.set(s, s, s); } }); const btn = (id, fn) => document.getElementById(id).addEventListener("click", fn); btn("sstvto-control-x-shift-plus-one", () => this._bumpPos("x", 1, "sstvto-control-x-shift")); btn("sstvto-control-x-shift-plus-point-one", () => this._bumpPos("x", 0.1, "sstvto-control-x-shift")); btn("sstvto-control-x-shift-minus-one", () => this._bumpPos("x", -1, "sstvto-control-x-shift")); btn("sstvto-control-x-shift-minus-point-one", () => this._bumpPos("x", -0.1, "sstvto-control-x-shift")); btn("sstvto-control-y-shift-plus-one", () => this._bumpPos("y", 1, "sstvto-control-y-shift")); btn("sstvto-control-y-shift-plus-point-one", () => this._bumpPos("y", 0.1, "sstvto-control-y-shift")); btn("sstvto-control-y-shift-minus-one", () => this._bumpPos("y", -1, "sstvto-control-y-shift")); btn("sstvto-control-y-shift-minus-point-one", () => this._bumpPos("y", -0.1, "sstvto-control-y-shift")); btn("sstvto-control-z-shift-plus-one", () => this._bumpPos("z", 1, "sstvto-control-z-shift")); btn("sstvto-control-z-shift-plus-point-one", () => this._bumpPos("z", 0.1, "sstvto-control-z-shift")); btn("sstvto-control-z-shift-minus-one", () => this._bumpPos("z", -1, "sstvto-control-z-shift")); btn("sstvto-control-z-shift-minus-point-one", () => this._bumpPos("z", -0.1, "sstvto-control-z-shift")); btn("sstvto-control-x-tilt-plus-one", () => this._bumpRotX(1, "sstvto-control-x-tilt")); btn("sstvto-control-x-tilt-plus-point-one", () => this._bumpRotX(0.1, "sstvto-control-x-tilt")); btn("sstvto-control-x-tilt-minus-one", () => this._bumpRotX(-1, "sstvto-control-x-tilt")); btn("sstvto-control-x-tilt-minus-point-one", () => this._bumpRotX(-0.1, "sstvto-control-x-tilt")); btn("sstvto-control-scale-plus-one", () => this._bumpScale(1, "sstvto-control-scale")); btn("sstvto-control-scale-plus-point-one", () => this._bumpScale(0.1, "sstvto-control-scale")); btn("sstvto-control-scale-minus-one", () => this._bumpScale(-1, "sstvto-control-scale")); btn("sstvto-control-scale-minus-point-one", () => this._bumpScale(-0.1, "sstvto-control-scale")); document.getElementById("ssvto-controls-button").addEventListener("click", () => { document.getElementById("ssvto-controls").style.display = "flex"; document.getElementById("ssvto-controls-button").style.display = "none"; }); document.getElementById("ssvvt-control-save-button").addEventListener("click", async () => { const model = this.ssto_config.products[this.product_index]; const adjustments = { x_shift: document.getElementById("sstvto-control-x-shift").value, y_shift: document.getElementById("sstvto-control-y-shift").value, z_shift: document.getElementById("sstvto-control-z-shift").value, x_tilt: document.getElementById("sstvto-control-x-tilt").value, scale: document.getElementById("sstvto-control-scale").value, }; model.adjustments_json = JSON.stringify(adjustments); await this.save_adjustments(model); }); } _bumpPos(axis, delta, inputId) { if (!this.model_scene) return; this.model_scene.position[axis] += delta; document.getElementById(inputId).value = this.model_scene.position[axis]; } _bumpRotX(delta, inputId) { if (!this.model_scene) return; this.model_scene.rotation.x += delta; document.getElementById(inputId).value = this.model_scene.rotation.x; } _bumpScale(delta, inputId) { if (!this.model_scene) return; const s = this.model_scene.scale.x + delta; this.model_scene.scale.set(s, s, s); document.getElementById(inputId).value = s; } async save_adjustments(model) { this.loading.style.display = "flex"; const response = await fetch("https://portal.safestyle.com.au/service/ssvto-adjustments", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(model), }); await response.json(); this.loading.style.display = "none"; } run_ssvto() { const self = this; this.createFaceLandmarker().then(() => { if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) { this.loading.style.display = "none"; document.querySelector(".ssvto-app-init").innerHTML = '
Unable to access camera in this browser.

'; document.getElementById("ssvto-init-cancel-button").onclick = function () { if (self.webcamRunning) self.webcamRunning = false; if (self.stream) self.stream.getTracks().forEach((track) => track.stop()); const container = document.querySelector(".ssvto-container"); if (container) document.body.removeChild(container); document.body.classList.remove("noscroll"); }; return; } navigator.mediaDevices .getUserMedia({ video: { width: 640 } }) .then((stream) => { this.stream = stream; this.video.srcObject = stream; this.webcamRunning = true; document.querySelector(".ssvto-app-init").style.display = "none"; document.querySelector(".ssvto-app").style.display = "flex"; let started = false; const start_video_pipeline = async () => { if (started) return; started = true; // Hide DOM video; we render it inside WebGL this.video.style.display = "none"; // Create video background once we have dimensions this.initVideoBackground(); // initial sizing this.handleResize(); self.predictWebcam(); this.webcam_running = true; this.check_disable_loader(); }; self.video.addEventListener("loadeddata", start_video_pipeline, { once: true, }); self.video.addEventListener("loadedmetadata", start_video_pipeline, { once: true, }); // Explicit play helps some desktop browsers start stream decoding reliably. this.video.play().catch((error) => { console.error("SSTO video.play() failed", error); }); }) .catch((error) => { console.error("SSTO getUserMedia failed", error); this.loading.style.display = "none"; document.querySelector(".ssvto-app-init").innerHTML = '
Unable to access camera.

Check browser camera permissions and try again.

'; document.getElementById("ssvto-init-cancel-button").onclick = function () { if (self.webcamRunning) self.webcamRunning = false; if (self.stream) self.stream.getTracks().forEach((track) => track.stop()); const container = document.querySelector(".ssvto-container"); if (container) document.body.removeChild(container); document.body.classList.remove("noscroll"); }; }); // keep your original behavior this.webcamRunning = false; this.loader = new GLTFLoader(); this.DRACOLoader = new DRACOLoader(); this.DRACOLoader.setDecoderPath("https://www.gstatic.com/draco/v1/decoders/"); this.loader.setDRACOLoader(this.DRACOLoader); // Foreground scene this.scene = new THREE.Scene(); this.renderer = new THREE.WebGLRenderer({ canvas: this.canvas_element, alpha: false, // camera is in-canvas now antialias: true, }); const environment = new RoomEnvironment(); const pmremGenerator = new THREE.PMREMGenerator(this.renderer); this.renderer.toneMapping = THREE.ACESFilmicToneMapping; this.renderer.toneMappingExposure = 0.5; this.scene.environment = pmremGenerator.fromScene(environment).texture; this.renderer.outputEncoding = THREE.sRGBEncoding; this.renderer.localClippingEnabled = true; this.faceGroup = new THREE.Group(); this.faceGroup.matrixAutoUpdate = false; this.scene.add(this.faceGroup); this.clipPlaneVector = new THREE.Vector3(0, 0, 1); this.clipPlane = new THREE.Plane(this.clipPlaneVector, 84); this.clipPlanes = [this.clipPlane]; const model = this.ssto_config.products[this.product_index]; this.load_model(model); }); } // ----- NEW: WebGL background video compositing ----- // DROP-IN: replace your current initVideoBackground() with this version. // It fixes the “lighter” camera by bypassing tone mapping on the background // and using sRGB encoding for the video texture (Three r129 compatible). initVideoBackground() { this.bgScene = new THREE.Scene(); this.bgCamera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1); this.videoTexture = new THREE.VideoTexture(this.video); this.videoTexture.minFilter = THREE.LinearFilter; this.videoTexture.magFilter = THREE.LinearFilter; this.videoTexture.generateMipmaps = false; this.videoTexture.wrapS = THREE.ClampToEdgeWrapping; this.videoTexture.wrapT = THREE.ClampToEdgeWrapping; // ✅ helps match DOM
Trade Range

Built for the toughest worksites, the Safestyle Trade Range is designed to last. Every pair features anti-scratch and anti-fog coatings so you can keep a clear view no matter the conditions. Our lens range covers it all, whether you’re working inside, outside, or moving between the two.

My bag

Empty bag

Your bag is currently empty.

Don't forget about your free gift!