Change camera position

Open in CodeSandbox

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
        <script crossorigin src="https://cdn.jsdelivr.net/npm/@babel/standalone@7/babel.min.js"></script>
        <!-- To make the map appear, you must add your apikey -->
        <script src="https://js.api.mappable.world/v3/?apikey=<YOUR_APIKEY>&lang=en_US" type="text/javascript"></script>

        <script
            data-plugins="transform-modules-umd"
            data-presets="typescript"
            type="text/babel"
            src="../variables.ts"
        ></script>
        <script
            data-plugins="transform-modules-umd"
            data-presets="typescript"
            type="text/babel"
            src="./common.ts"
        ></script>
        <script data-plugins="transform-modules-umd" data-presets="typescript" type="text/babel">
            import {LOCATION} from '../variables';
            import {DEG_TO_RAD} from './common';
            
            window.map = null;
            
            main();
            
            async function main() {
                // Waiting for all api elements to be loaded
                await mappable.ready;
                const {MMap, MMapDefaultSchemeLayer, MMapListener, MMapControls, MMapControl} = mappable;
            
                // Initialize the map
                map = new MMap(
                    // Pass the link to the HTMLElement of the container
                    document.getElementById('app'),
                    // Pass the map initialization parameters
                    {location: LOCATION, showScaleInCopyrights: true, camera: {tilt: 40 * DEG_TO_RAD}},
                    // Add a map scheme layer
                    [new MMapDefaultSchemeLayer({})]
                );
            
                let hasAutoRotate = mappable.MMap.defaultProps.mode === 'auto';
                let frame = 0;
            
                function onActionStartHandler() {
                    // Turn off the auto-rotation of the map flag at any event
                    hasAutoRotate = false;
                    const switchInput = document.getElementById('switch');
                    (switchInput as HTMLInputElement).checked = false;
                }
            
                // Creating a listener object
                const mapListener = new MMapListener({
                    layer: 'any',
                    // Adding an onActionStart handler to the listener
                    onActionStart: onActionStartHandler
                });
                map.addChild(mapListener);
            
                // Add a shared container for MMapControlButton's and add it to the map
                const controls = new MMapControls({position: 'top right'});
                map.addChild(controls);
            
                // Automatically rotate the camera
                function startAutoRotationCamera() {
                    if (hasAutoRotate) {
                        //  Divide degrees by 100 to slow rotation to ~10 degrees / sec
                        map.update({camera: {azimuth: map.azimuth + (10 * DEG_TO_RAD) / 120}});
                        // Request the next frame of the animation
                        frame = requestAnimationFrame(startAutoRotationCamera);
                    } else {
                        // If the automatic rotation mode is stopped then cancel the request for the next animation frame
                        cancelAnimationFrame(frame);
                    }
                }
            
                startAutoRotationCamera();
            
                // Add MMapControlButton's that will change the camera position when clicked
                function autoRotateBtnHandler() {
                    hasAutoRotate = !hasAutoRotate;
                    startAutoRotationCamera();
                }
            
                function rotateLeftBtnHandler() {
                    onActionStartHandler();
                    // Rotate the camera 30 degrees to the left (degrees need to be converted to radians)
                    map.update({camera: {azimuth: map.azimuth - 30 * DEG_TO_RAD, duration: 250}});
                }
            
                function rotateRightBtnHandler() {
                    onActionStartHandler();
                    // Rotate the camera 30 degrees to the right (degrees need to be converted to radians)
                    map.update({camera: {azimuth: map.azimuth + 30 * DEG_TO_RAD, duration: 250}});
                }
            
                function upTiltBtnHandler() {
                    onActionStartHandler();
                    // Tilt the camera up 10 degrees (degrees need to be converted to radians)
                    map.update({camera: {tilt: map.tilt - 10 * DEG_TO_RAD, duration: 250}});
                }
            
                function downTiltBtnHandler() {
                    onActionStartHandler();
                    // Tilt the camera down 10 degrees (degrees need to be converted to radians)
                    map.update({camera: {tilt: map.tilt + 10 * DEG_TO_RAD, duration: 250}});
                }
            
                // Create a custom control class for map camera position management
                interface CameraPositionControlProps {
                    downTiltBtnHandler: () => void;
            
                    rotateRightBtnHandler: () => void;
            
                    upTiltBtnHandler: () => void;
            
                    rotateLeftBtnHandler: () => void;
            
                    autoRotateBtnHandler: () => void;
                }
            
                class CameraPositionControl extends mappable.MMapComplexEntity<CameraPositionControlProps> {
                    private _element: HTMLDivElement;
            
                    private _detachDom: () => void;
            
                    // Method for create a DOM control element
                    _createElement(props: CameraPositionControlProps) {
                        const {
                            downTiltBtnHandler,
                            rotateRightBtnHandler,
                            upTiltBtnHandler,
                            rotateLeftBtnHandler,
                            autoRotateBtnHandler
                        } = props;
            
                        const controlContainer = document.createElement('div');
                        controlContainer.classList.add('control');
            
                        const controlRotateElement = document.createElement('div');
                        controlRotateElement.classList.add('control__auto-rotate');
            
                        const controlRotateTextElement = document.createElement('p');
                        controlRotateTextElement.classList.add('auto-rotate__text');
                        controlRotateTextElement.innerText = 'Auto Rotate';
            
                        const controlRotateSwitchElement = document.createElement('label');
                        controlRotateSwitchElement.classList.add('switch');
            
                        const controlRotateSwitchInput = document.createElement('input');
                        controlRotateSwitchInput.type = 'checkbox';
                        controlRotateSwitchInput.onchange = autoRotateBtnHandler;
                        controlRotateSwitchInput.checked = hasAutoRotate;
                        controlRotateSwitchInput.id = 'switch';
            
                        const controlRotateSwitchInputSpan = document.createElement('span');
                        controlRotateSwitchInputSpan.classList.add('slider');
            
                        controlRotateSwitchElement.appendChild(controlRotateSwitchInput);
                        controlRotateSwitchElement.appendChild(controlRotateSwitchInputSpan);
            
                        controlRotateElement.appendChild(controlRotateTextElement);
                        controlRotateElement.appendChild(controlRotateSwitchElement);
            
                        const controlDividerElement = document.createElement('div');
                        controlDividerElement.classList.add('control__divider');
            
                        const controlButtonsElement = document.createElement('div');
                        controlButtonsElement.classList.add('control__buttons');
            
                        const controlButtonsBlockFirst = document.createElement('div');
                        controlButtonsBlockFirst.classList.add('buttons__block');
            
                        const controlButtonTiltForward = document.createElement('button');
                        controlButtonTiltForward.classList.add('button');
                        controlButtonTiltForward.classList.add('tilt-forward');
                        controlButtonTiltForward.onclick = upTiltBtnHandler;
                        controlButtonTiltForward.innerText = 'tilt forward';
            
                        controlButtonsBlockFirst.appendChild(controlButtonTiltForward);
            
                        const controlButtonsBlockSecond = document.createElement('div');
                        controlButtonsBlockSecond.classList.add('buttons__block');
            
                        const controlButtonRotateLeft = document.createElement('button');
                        controlButtonRotateLeft.classList.add('button');
                        controlButtonRotateLeft.classList.add('rotate-left');
                        controlButtonRotateLeft.onclick = rotateLeftBtnHandler;
                        controlButtonRotateLeft.innerText = 'rotate left';
            
                        const controlButtonTiltBack = document.createElement('button');
                        controlButtonTiltBack.classList.add('button');
                        controlButtonTiltBack.classList.add('tilt-back');
                        controlButtonTiltBack.onclick = downTiltBtnHandler;
                        controlButtonTiltBack.innerText = 'tilt back';
            
                        const controlButtonRotateRight = document.createElement('button');
                        controlButtonRotateRight.classList.add('button');
                        controlButtonRotateRight.classList.add('rotate-right');
                        controlButtonRotateRight.onclick = rotateRightBtnHandler;
                        controlButtonRotateRight.innerText = 'rotate right';
            
                        controlButtonsBlockSecond.appendChild(controlButtonRotateLeft);
                        controlButtonsBlockSecond.appendChild(controlButtonTiltBack);
                        controlButtonsBlockSecond.appendChild(controlButtonRotateRight);
            
                        controlButtonsElement.appendChild(controlButtonsBlockFirst);
                        controlButtonsElement.appendChild(controlButtonsBlockSecond);
            
                        controlContainer.appendChild(controlRotateElement);
                        controlContainer.appendChild(controlDividerElement);
                        controlContainer.appendChild(controlButtonsElement);
            
                        return controlContainer;
                    }
            
                    // Method for attaching the control to the map
                    _onAttach() {
                        this._element = this._createElement(this._props);
                        this._detachDom = mappable.useDomContext(this, this._element, this._element);
                    }
            
                    // Method for detaching control from the map
                    _onDetach() {
                        this._detachDom();
                        this._detachDom = null;
                        this._element = null;
                    }
                }
            
                const control = new MMapControl();
            
                control.addChild(
                    new CameraPositionControl({
                        downTiltBtnHandler,
                        autoRotateBtnHandler,
                        rotateLeftBtnHandler,
                        rotateRightBtnHandler,
                        upTiltBtnHandler
                    })
                );
            
                controls.addChild(control);
            }
        </script>

        <style> html, body, #app { width: 100%; height: 100%; margin: 0; padding: 0; font-family: Arial, Helvetica, sans-serif; } .toolbar { position: absolute; z-index: 1000; top: 0; left: 0; display: flex; align-items: center; padding: 16px; } .toolbar a { padding: 16px; }  </style>
        <link rel="stylesheet" href="./common.css" />
        <link rel="stylesheet" href="../variables.css" />
    </head>
    <body>
        <div id="app"></div>
    </body>
</html>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
        <script crossorigin src="https://cdn.jsdelivr.net/npm/react@17/umd/react.production.min.js"></script>
        <script crossorigin src="https://cdn.jsdelivr.net/npm/react-dom@17/umd/react-dom.production.min.js"></script>
        <script crossorigin src="https://cdn.jsdelivr.net/npm/@babel/standalone@7/babel.min.js"></script>
        <!-- To make the map appear, you must add your apikey -->
        <script src="https://js.api.mappable.world/v3/?apikey=<YOUR_APIKEY>&lang=en_US" type="text/javascript"></script>

        <script
            data-plugins="transform-modules-umd"
            data-presets="typescript"
            type="text/babel"
            src="../variables.ts"
        ></script>
        <script
            data-plugins="transform-modules-umd"
            data-presets="typescript"
            type="text/babel"
            src="./common.ts"
        ></script>
        <script data-plugins="transform-modules-umd" data-presets="react, typescript" type="text/babel">
            import {LOCATION} from '../variables';
            import {DEG_TO_RAD} from './common';
            
            window.map = null;
            
            main();
            
            async function main() {
                // For each object in the JS API, there is a React counterpart
                // To use the React version of the API, include the module @mappable-world/mappable-reactify
                const [mappableReact] = await Promise.all([mappable.import('@mappable-world/mappable-reactify'), mappable.ready]);
                const reactify = mappableReact.reactify.bindTo(React, ReactDOM);
                const {MMap, MMapDefaultSchemeLayer, MMapListener, MMapControls, MMapControl} = reactify.module(mappable);
                const {useState, useEffect, useRef, useCallback} = React;
            
                function App() {
                    const [hasAutoRotate, setAutoRotate] = useState(mappable.MMap.defaultProps.mode === 'auto');
                    const [mapAzimuth, setMapAzimuth] = useState(0);
                    const [mapTilt, setMapTilt] = useState(40 * DEG_TO_RAD);
                    const frame = useRef<number>(null);
            
                    // Automatically rotate the camera
                    const startAutoRotationCamera = useCallback(() => {
                        if (hasAutoRotate) {
                            //  Divide degrees by 100 to slow rotation to ~20 degrees / sec
                            setMapAzimuth(map.azimuth + (10 * DEG_TO_RAD) / 100);
                            // Request the next frame of the animation
                            frame.current = requestAnimationFrame(startAutoRotationCamera);
                        } else {
                            // If the automatic rotation mode is stopped then cancel the request for the next animation frame
                            cancelAnimationFrame(frame.current);
                        }
                    }, [hasAutoRotate]);
            
                    useEffect(() => {
                        // Update ref to new animation frame ID
                        frame.current = requestAnimationFrame(startAutoRotationCamera);
            
                        // Kill animation cycle on component unmount
                        return () => cancelAnimationFrame(frame.current);
                    }, [startAutoRotationCamera]);
            
                    const onActionStartHandler = useCallback(() => {
                        // Turn off the auto-rotation of the map flag at any event
                        setAutoRotate(false);
                    }, []);
            
                    const autoRotateBtnHandler = useCallback(() => {
                        setAutoRotate((prevAutoRotate) => !prevAutoRotate);
                    }, []);
            
                    const rotateLeftBtnHandler = useCallback(() => {
                        onActionStartHandler();
                        // Rotate the camera 30 degrees to the left (degrees need to be converted to radians)
                        setMapAzimuth(map.azimuth - 30 * DEG_TO_RAD);
                    }, []);
            
                    const rotateRightBtnHandler = useCallback(() => {
                        onActionStartHandler();
                        // Rotate the camera 30 degrees to the right (degrees need to be converted to radians)
                        setMapAzimuth(map.azimuth + 30 * DEG_TO_RAD);
                    }, []);
            
                    const tiltUpBtnHandler = useCallback(() => {
                        onActionStartHandler();
                        // Tilt the camera up 10 degrees (degrees need to be converted to radians)
                        setMapTilt(map.tilt - 10 * DEG_TO_RAD);
                    }, []);
            
                    const tiltDownBtnHandler = useCallback(() => {
                        onActionStartHandler();
                        // Tilt the camera down 10 degrees (degrees need to be converted to radians)
                        setMapTilt(map.tilt + 10 * DEG_TO_RAD);
                    }, []);
            
                    return (
                        // Initialize the map and pass initialization parameters
                        <MMap
                            location={LOCATION}
                            showScaleInCopyrights={true}
                            camera={{azimuth: mapAzimuth, tilt: mapTilt, duration: hasAutoRotate ? 0 : 250}}
                            ref={(x) => (map = x)}
                        >
                            {/* Add a map scheme layer */}
                            <MMapDefaultSchemeLayer />
            
                            {/* Creating a listener component and adding an onActionStart handler to it */}
                            <MMapListener onActionStart={onActionStartHandler} />
            
                            {/* Add a shared container for MMapControlButton's */}
                            <MMapControls position="top right" orientation="vertical">
                                {/* Add MMapControlButton's that will change the camera position when clicked */}
                                <MMapControl>
                                    <div className="control">
                                        <div className="control__auto-rotate">
                                            <p className="auto-rotate__text">Auto Rotate</p>
                                            <label className="switch">
                                                <input type="checkbox" checked={hasAutoRotate} onChange={autoRotateBtnHandler} />
                                                <span className="slider" />
                                            </label>
                                        </div>
            
                                        <div className="control__divider" />
            
                                        <div className="control__buttons">
                                            <div className="buttons__block">
                                                <button className="button tilt-forward" onClick={tiltUpBtnHandler}>
                                                    tilt forward
                                                </button>
                                            </div>
                                            <div className="buttons__block">
                                                <button className="button rotate-left" onClick={rotateLeftBtnHandler}>
                                                    rotate left
                                                </button>
                                                <button className="button tilt-back" onClick={tiltDownBtnHandler}>
                                                    tilt back
                                                </button>
                                                <button className="button rotate-right" onClick={rotateRightBtnHandler}>
                                                    rotate right
                                                </button>
                                            </div>
                                        </div>
                                    </div>
                                </MMapControl>
                            </MMapControls>
                        </MMap>
                    );
                }
            
                ReactDOM.render(
                    <React.StrictMode>
                        <App />
                    </React.StrictMode>,
                    document.getElementById('app')
                );
            }
        </script>

        <style> html, body, #app { width: 100%; height: 100%; margin: 0; padding: 0; font-family: Arial, Helvetica, sans-serif; } .toolbar { position: absolute; z-index: 1000; top: 0; left: 0; display: flex; align-items: center; padding: 16px; } .toolbar a { padding: 16px; }  </style>
        <link rel="stylesheet" href="./common.css" />
        <link rel="stylesheet" href="../variables.css" />
    </head>
    <body>
        <div id="app"></div>
    </body>
</html>
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
        <script crossorigin src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.js"></script>
        <script crossorigin src="https://cdn.jsdelivr.net/npm/@babel/standalone@7/babel.min.js"></script>
        <!-- To make the map appear, you must add your apikey -->
        <script src="https://js.api.mappable.world/v3/?apikey=<YOUR_APIKEY>&lang=en_US" type="text/javascript"></script>

        <script
            data-plugins="transform-modules-umd"
            data-presets="typescript"
            type="text/babel"
            src="../variables.ts"
        ></script>
        <script
            data-plugins="transform-modules-umd"
            data-presets="typescript"
            type="text/babel"
            src="./common.ts"
        ></script>
        <script data-plugins="transform-modules-umd" data-presets="typescript" type="text/babel">
            import {LOCATION} from '../variables';
            import {DEG_TO_RAD} from './common';
            
            window.map = null;
            
            async function main() {
                // For each object in the JS API, there is a Vue counterpart
                // To use the Vue version of the API, include the module @mappable-world/mappable-vuefy
                const [mappableVue] = await Promise.all([mappable.import('@mappable-world/mappable-vuefy'), mappable.ready]);
                const vuefy = mappableVue.vuefy.bindTo(Vue);
                const {MMap, MMapDefaultSchemeLayer, MMapListener, MMapControls, MMapControl, MMapControlButton} =
                    vuefy.module(mappable);
            
                const app = Vue.createApp({
                    setup() {
                        const location = Vue.ref(LOCATION);
                        const refMap = (ref) => {
                            window.map = ref?.entity;
                        };
                        const hasAutoRotate = Vue.ref(mappable.MMap.defaultProps.mode === 'auto');
                        const mapAzimuth = Vue.ref(0);
                        const mapTilt = Vue.ref(40 * DEG_TO_RAD);
                        let frameId;
            
                        const autoRotateCamera = () => {
                            if (hasAutoRotate.value) {
                                mapAzimuth.value += (10 * DEG_TO_RAD) / 100;
                                frameId = requestAnimationFrame(autoRotateCamera);
                            }
                        };
            
                        Vue.onMounted(() => {
                            frameId = requestAnimationFrame(autoRotateCamera);
                        });
            
                        Vue.onUnmounted(() => {
                            cancelAnimationFrame(frameId);
                        });
            
                        const onActionStartHandler = () => {
                            hasAutoRotate.value = false;
                        };
            
                        const autoRotateBtnHandler = () => {
                            hasAutoRotate.value = !hasAutoRotate.value;
                            frameId = requestAnimationFrame(autoRotateCamera);
                        };
            
                        const rotateLeftBtnHandler = () => {
                            onActionStartHandler();
                            mapAzimuth.value = map.azimuth - 30 * DEG_TO_RAD;
                        };
            
                        const rotateRightBtnHandler = () => {
                            onActionStartHandler();
                            mapAzimuth.value = map.azimuth + 30 * DEG_TO_RAD;
                        };
            
                        const tiltUpBtnHandler = () => {
                            onActionStartHandler();
                            mapTilt.value = map.tilt - 10 * DEG_TO_RAD;
                        };
            
                        const tiltDownBtnHandler = () => {
                            onActionStartHandler();
                            mapTilt.value = map.tilt + 10 * DEG_TO_RAD;
                        };
            
                        return {
                            location,
                            refMap,
                            hasAutoRotate,
                            mapAzimuth,
                            mapTilt,
                            onActionStartHandler,
                            autoRotateBtnHandler,
                            rotateLeftBtnHandler,
                            rotateRightBtnHandler,
                            tiltUpBtnHandler,
                            tiltDownBtnHandler
                        };
                    },
                    components: {
                        MMap,
                        MMapDefaultSchemeLayer,
                        MMapListener,
                        MMapControls,
                        MMapControl,
                        MMapControlButton
                    },
                    template: `
                  <MMap
                    :location="location"
                    :camera="{ azimuth: mapAzimuth, tilt: mapTilt, duration: hasAutoRotate ? 0 : 250 }"
                    :ref="refMap"
                  >
                    <MMapDefaultSchemeLayer/>
                    <MMapListener @action-start="onActionStartHandler"/>
            
                    <MMapControls position="top right">
                      <MMapControl>
                        <div class="control">
                          <div class="control__auto-rotate">
                            <p class="auto-rotate__text">Auto Rotate</p>
                            <label class="switch">
                              <input type="checkbox" :checked="hasAutoRotate" @change="autoRotateBtnHandler"/>
                              <span class="slider"/>
                            </label>
                          </div>
            
                          <div class="control__divider"/>
            
                          <div class="control__buttons">
                            <div class="buttons__block">
                              <button class="button tilt-forward" @click="tiltUpBtnHandler">
                                tilt forward
                              </button>
                            </div>
                            <div class="buttons__block">
                              <button class="button rotate-left" @click="rotateLeftBtnHandler">
                                rotate left
                              </button>
                              <button class="button tilt-back" @click="tiltDownBtnHandler">
                                tilt back
                              </button>
                              <button class="button rotate-right" @click="rotateRightBtnHandler">
                                rotate right
                              </button>
                            </div>
                          </div>
                        </div>
                      </MMapControl>
                    </MMapControls>
                  </MMap>
                `
                });
            
                app.mount('#app');
            }
            
            main();
        </script>

        <style> html, body, #app { width: 100%; height: 100%; margin: 0; padding: 0; font-family: Arial, Helvetica, sans-serif; } .toolbar { position: absolute; z-index: 1000; top: 0; left: 0; display: flex; align-items: center; padding: 16px; } .toolbar a { padding: 16px; }  </style>
        <link rel="stylesheet" href="./common.css" />
        <link rel="stylesheet" href="../variables.css" />
    </head>
    <body>
        <div id="app"></div>
    </body>
</html>
import type {MMapLocationRequest} from '@mappable-world/mappable-types';

export const LOCATION: MMapLocationRequest = {
    center: [55.274, 25.197], // starting position [lng, lat]
    zoom: 16.5 // starting zoom
};
:root {
    --interact-action: #122db2;
}
export const DEG_TO_RAD = Math.PI / 180;
.control {
    padding: 16px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.control__auto-rotate {
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
}

.auto-rotate__text {
    font-size: 16px;
    color: #050d33;
    font-weight: 500;
}

.control__divider {
    width: 100%;
    height: 1px;
    background-color: #5c5e661a;
    margin: 8px 0;
    border: none;
}

.control__buttons {
    display: flex;
    flex-direction: column;
}

.buttons__block {
    display: flex;
    flex-direction: row;
    justify-content: center;
}

.button {
    color: #050d33;
    font-size: 12px;
    margin: 2px;
    display: flex;
    width: 84px;
    height: 68px;
    padding: 34px 8px 10px 8px;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 6px;
    border-radius: 12px;
    background-color: rgba(92, 94, 102, 0.06);
    border: none;
    cursor: pointer;
    background-repeat: no-repeat;
    background-position: center 30%;
}

.button.tilt-forward {
    background-image: url('./tilt-forward.svg?inline');
}
.button.tilt-back {
    background-image: url('./tilt-back.svg?inline');
}
.button.rotate-left {
    background-image: url('./rotate-left.svg?inline');
}
.button.rotate-right {
    background-image: url('./rotate-right.svg?inline');
}

/* The switch - the box around the slider */
.switch {
    position: relative;
    display: inline-block;
    width: 34px;
    height: 20px;
}

/* Hide default HTML checkbox */
.switch input {
    opacity: 0;
    width: 0;
    height: 0;
}

/* The slider */
.slider {
    position: absolute;
    cursor: pointer;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: #ccc;
    -webkit-transition: 0.4s;
    transition: 0.4s;
    border-radius: 34px;
}

.slider:before {
    position: absolute;
    content: '';
    height: 16px;
    width: 16px;
    left: 2px;
    bottom: 2px;
    background-color: white;
    -webkit-transition: 0.4s;
    transition: 0.4s;
    border-radius: 50%;
}

input:checked + .slider {
    background-color: var(--interact-action);
}

input:focus + .slider {
    box-shadow: 0 0 1px var(--interact-action);
}

input:checked + .slider:before {
    -webkit-transform: translateX(14px);
    -ms-transform: translateX(14px);
    transform: translateX(14px);
}