NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @namespace https://openuserjs.org/users/KvByte // @name Tinkercad Mobile // @description Converts touch to mouse events, and adjust the interface for mobile. // @copyright 2021, KvByte (https://openuserjs.org/users/KvByte) // @license MIT // @version 0.1.07 // @include https://www.tinkercad.com/things/* // @icon https://www.google.com/s2/favicons?domain=tinkercad.com // @grant none // @noframes // ==/UserScript== // ==OpenUserJS== // @author KvByte // ==/OpenUserJS== (function () { 'use strict'; console.log("Start User Script"); // Based on 'Mickey Shine' solution, created Tap to "click", and updated from initMouseEvent (deprecated) to MouseEvent (new) // https://stackoverflow.com/questions/1517924/javascript-mapping-touch-events-to-mouse-events let lastTouchStart = 0; function touchToMouseHandler(event) { // Get first touch input let touches = event.changedTouches, first = touches[0], type = ""; // Get the correct type to simulate switch (event.type) { case "touchstart": type = "mousedown"; lastTouchStart = new Date().getTime(); break; case "touchmove": type = "mousemove"; break; case "touchend": type = "mouseup"; break; case "touchend": type = "mouseup"; break; default: return; } // dispatch the simulated type const mouseEventInitDictionary = { bubbles: true, cancelable: true, clientX: first.clientX, clientY: first.clientY, screenX: first.screenX, screenY: first.screenY } const mouseEvent = new MouseEvent(type, mouseEventInitDictionary); first.target.dispatchEvent(mouseEvent); // Convert Tap to "click" event if (type == "mouseup") { const currentTime = new Date().getTime(); if (currentTime - lastTouchStart <= 200 /*ms*/) { // dispatch the click type const clickEvent = new MouseEvent("click", mouseEventInitDictionary); first.target.dispatchEvent(clickEvent); } } // cancels the bubbling of the touch event event.preventDefault(); } function initTouchToMouseConverter(el) { el.addEventListener("touchstart", touchToMouseHandler, true); el.addEventListener("touchmove", touchToMouseHandler, true); el.addEventListener("touchend", touchToMouseHandler, true); el.addEventListener("touchcancel", touchToMouseHandler, true); } // Tinkercad let tinkercadVisualChanges = () => { console.log("Tinkercad Changes Start"); // Start Mouse Simulation initTouchToMouseConverter(document.querySelector("#breadboardTab svg")); // CSS var style = document.createElement('style'); style.innerHTML = ` /* Dont scroll body */ body { touchAction: none; overflow: hidden; } /* Remove time counting in simulation */ .sitemenu__info{ display: none; } /* Remove text button */ #CODE_EDITOR_ID .circ_btn__txt{ display: none; } /* Increase size of collapseButton */ .editor__sidebar__collapseButton{ width: 25px; left: -25px; } /* Hide Inspector under components */ .inspector{ right: 25px !important; } /* ZOOM buttons */ #ZOOM_IN_, #ZOOM_OUT_{ line-height: 32px; text-align: center; font-size: 25px; user-select: none; -moz-user-select: none; -webkit-user-select: none; } /* Full Screen */ #FULLSCREEN_{ } .button-fullscreen-svg- { background: url('data:image/svg+xml;utf8,<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="expand-arrows-alt" class="svg-inline--fa fa-expand-arrows-alt fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M448 344v112a23.94 23.94 0 0 1-24 24H312c-21.39 0-32.09-25.9-17-41l36.2-36.2L224 295.6 116.77 402.9 153 439c15.09 15.1 4.39 41-17 41H24a23.94 23.94 0 0 1-24-24V344c0-21.4 25.89-32.1 41-17l36.19 36.2L184.46 256 77.18 148.7 41 185c-15.1 15.1-41 4.4-41-17V56a23.94 23.94 0 0 1 24-24h112c21.39 0 32.09 25.9 17 41l-36.2 36.2L224 216.4l107.23-107.3L295 73c-15.09-15.1-4.39-41 17-41h112a23.94 23.94 0 0 1 24 24v112c0 21.4-25.89 32.1-41 17l-36.19-36.2L263.54 256l107.28 107.3L407 327.1c15.1-15.2 41-4.5 41 16.9z"></path></svg>') no-repeat; background-size: 20px 20px; background-position: 5px 5px; } `; document.head.appendChild(style); // Add ZOOM buttons in HTML let htmlZoomInOut = ` <a id="ZOOM_IN_" class="zoomToFit js-zoomToFit viewcube__button viewcube__button__border js-analytics" style="top: 48px;left:8px;" title="Aumentar zoom">+</a> <a id="ZOOM_OUT_" class="zoomToFit js-zoomToFit viewcube__button viewcube__button__border js-analytics" style="top: 88px;left:8px;" title="Diminuir zoom">-</a></div> `; document.querySelector("#viewcube").insertAdjacentHTML('beforeend', htmlZoomInOut); // Set values const scrollEl = document.querySelector("#breadboardTab svg"); const docCenterHeight = document.defaultView.innerHeight / 2; const docwidth = document.defaultView.innerWidth; const sidebarColapsed = () => document.querySelectorAll(".editor__sidebar__collapseButton_collapsed").length; const docCenterwidth = () => sidebarColapsed() ? docwidth / 2 : (docwidth - 276) / 2; const wheelEventInitDictionary = { bubbles: true, cancelable: true, clientY: docCenterHeight, screenY: docCenterHeight, pageY: docCenterHeight } // Zoom Functions document.querySelector("#ZOOM_IN_").onclick = () => scrollEl.dispatchEvent(new WheelEvent("wheel", { ...wheelEventInitDictionary, clientX: docCenterwidth(), screenX: docCenterwidth(), pageX: docCenterwidth(), deltaY: -400 })); document.querySelector("#ZOOM_OUT_").onclick = () => scrollEl.dispatchEvent(new WheelEvent("wheel", { ...wheelEventInitDictionary, clientX: docCenterwidth(), screenX: docCenterwidth(), pageX: docCenterwidth(), deltaY: 400 })); // Add Fullscreen button let htmlFullScreen = ` <a id="FULLSCREEN_" class="zoomToFit js-zoomToFit viewcube__button viewcube__button__border js-analytics" style="top: 128px;left:8px;" title="Tela cheia"> <div class="button-container-svg button-fullscreen-svg-"></div> </a> `; document.querySelector("#viewcube").insertAdjacentHTML('beforeend', htmlFullScreen); // Zoom Functions function toggleFullscreen(elem) { elem = elem || document.documentElement; if (!document.fullscreenElement){ if (elem.requestFullscreen) { elem.requestFullscreen(); } } else { if (document.exitFullscreen) { document.exitFullscreen(); } } } document.querySelector("#FULLSCREEN_").onclick = () => toggleFullscreen(); }; const canStart = () => { if (document.querySelector(".loading") && document.querySelector(".loading").style.display === "none") { setTimeout(tinkercadVisualChanges, 1000); } else { setTimeout(canStart, 1000); } } setTimeout(canStart, 2000); })();