Planets Image Map
Instructions: Mouse over the planets to see their names and use the check box to show and hide the map overlay.
- Vanilla
- React
- Vue
import Konva from 'konva'; const stage = new Konva.Stage({ container: 'container', width: window.innerWidth, height: window.innerHeight, }); const planetsLayer = new Konva.Layer(); const circlesLayer = new Konva.Layer(); const messageLayer = new Konva.Layer(); stage.add(planetsLayer); stage.add(circlesLayer); stage.add(messageLayer); const text = new Konva.Text({ x: 10, y: 10, fontFamily: 'Calibri', fontSize: 24, text: '', fill: 'white', }); messageLayer.add(text); function writeMessage(message) { text.text(message); } const planets = { Mercury: { x: 46, y: 126, radius: 32, }, Venus: { x: 179, y: 126, radius: 79, }, Earth: { x: 366, y: 127, radius: 85, }, Mars: { x: 515, y: 127, radius: 45, }, }; // create checkbox const container = document.createElement('div'); container.style.position = 'absolute'; container.style.top = '10px'; container.style.left = '10px'; container.style.zIndex = '99999'; container.innerHTML = ` <label style="color: white;"> <input type="checkbox" id="checkbox" /> Show map overlay </label>`; document.body.appendChild(container); // draw shape overlays for (const key in planets) { const planet = planets[key]; const planetOverlay = new Konva.Circle({ x: planet.x, y: planet.y, radius: planet.radius, }); planetOverlay.on('mouseover', () => { writeMessage(key); }); planetOverlay.on('mouseout', () => { writeMessage(''); }); circlesLayer.add(planetOverlay); } const checkbox = document.getElementById('checkbox'); checkbox.addEventListener('click', () => { const shapes = circlesLayer.getChildren(); shapes.forEach(shape => { const f = shape.fill(); shape.fill(f === 'red' ? null : 'red'); }); }); // load the image Konva.Image.fromURL('https://konvajs.org/assets/planets.png', (planetsImage) => { planetsLayer.add(planetsImage); });
import { Stage, Layer, Image, Circle, Text } from 'react-konva'; import { useState } from 'react'; import useImage from 'use-image'; const planets = { Mercury: { x: 46, y: 126, radius: 32, }, Venus: { x: 179, y: 126, radius: 79, }, Earth: { x: 366, y: 127, radius: 85, }, Mars: { x: 515, y: 127, radius: 45, }, }; const CheckboxStyles = { container: { position: 'absolute', left: '10px', top: '10px', zIndex: 99999, }, label: { color: 'white', display: 'flex', alignItems: 'center', gap: '5px', cursor: 'pointer', }, input: { cursor: 'pointer', }, }; const App = () => { const [message, setMessage] = useState(''); const [showOverlay, setShowOverlay] = useState(false); const [planetsImage] = useImage('https://konvajs.org/assets/planets.png'); return ( <> <div style={CheckboxStyles.container}> <label style={CheckboxStyles.label}> <input type="checkbox" style={CheckboxStyles.input} checked={showOverlay} onChange={(e) => setShowOverlay(e.target.checked)} /> Show map overlay </label> </div> <Stage width={window.innerWidth} height={window.innerHeight}> <Layer> {planetsImage && <Image image={planetsImage} />} </Layer> <Layer> {Object.entries(planets).map(([name, planet]) => ( <Circle key={name} x={planet.x} y={planet.y} radius={planet.radius} fill={showOverlay ? 'red' : null} onMouseEnter={() => setMessage(name)} onMouseLeave={() => setMessage('')} /> ))} </Layer> <Layer> <Text x={10} y={10} fontFamily="Calibri" fontSize={24} text={message} fill="white" /> </Layer> </Stage> </> ); }; export default App;
<template> <div> <div :style="styles.container"> <label :style="styles.label"> <input type="checkbox" :style="styles.input" v-model="showOverlay" /> Show map overlay </label> </div> <v-stage :config="stageSize"> <v-layer> <v-image v-if="planetsImage" :config="{ image: planetsImage }" /> </v-layer> <v-layer> <v-circle v-for="(planet, name) in planets" :key="name" :config="{ x: planet.x, y: planet.y, radius: planet.radius, fill: showOverlay ? 'red' : null, }" @mouseenter="message = name" @mouseleave="message = ''" /> </v-layer> <v-layer> <v-text :config="textConfig" /> </v-layer> </v-stage> </div> </template> <script setup> import { ref, computed } from 'vue'; import { useImage } from 'vue-konva'; const message = ref(''); const showOverlay = ref(false); const [planetsImage] = useImage('https://konvajs.org/assets/planets.png'); const planets = { Mercury: { x: 46, y: 126, radius: 32, }, Venus: { x: 179, y: 126, radius: 79, }, Earth: { x: 366, y: 127, radius: 85, }, Mars: { x: 515, y: 127, radius: 45, }, }; const stageSize = { width: window.innerWidth, height: window.innerHeight, }; const styles = { container: { position: 'absolute', left: '10px', top: '10px', zIndex: 99999, }, label: { color: 'white', display: 'flex', alignItems: 'center', gap: '5px', cursor: 'pointer', }, input: { cursor: 'pointer', }, }; const textConfig = computed(() => ({ x: 10, y: 10, fontFamily: 'Calibri', fontSize: 24, text: message.value, fill: 'white', })); </script>