Skip to content

Commit a448918

Browse files
chore: wip
1 parent 7822d1f commit a448918

File tree

5 files changed

+813
-1
lines changed

5 files changed

+813
-1
lines changed

packages/vue/src/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import Italy from './components/VectorMaps/Italy.vue'
88
import Russia from './components/VectorMaps/Russia.vue'
99
import Spain from './components/VectorMaps/Spain.vue'
1010
import UnitedStates from './components/VectorMaps/UnitedStates.vue'
11+
import WorldMap from './components/VectorMaps/WorldMap.vue'
1112

1213
const plugin: Plugin = {
1314
install: (app: App) => {
@@ -20,10 +21,11 @@ const plugin: Plugin = {
2021
app.component('Italy', Italy)
2122
app.component('Russia', Russia)
2223
app.component('Spain', Spain)
24+
app.component('WorldMap', WorldMap)
2325
},
2426
}
2527

2628
export default plugin
2729

28-
export { Brasil, Canada, GoogleMap, Iraq, Italy, Russia, Spain, UnitedStates, VectorMap }
30+
export { Brasil, Canada, GoogleMap, Iraq, Italy, Russia, Spain, UnitedStates, VectorMap, WorldMap }
2931
export type { MapOptions } from '../../ts-maps/src/types'
Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
<script setup lang="ts">
2+
import type { MapOptions } from 'ts-maps'
3+
import { reactive, ref } from 'vue'
4+
import { Brasil } from 'ts-maps-vue'
5+
6+
interface EventData {
7+
type: string
8+
code?: string
9+
marker?: any
10+
time: string
11+
}
12+
13+
const isDarkTheme = ref(false)
14+
const lastEvent = ref<EventData | null>(null)
15+
16+
const options = reactive<Omit<MapOptions, 'selector'>>({
17+
backgroundColor: '#ffffff',
18+
zoomOnScroll: true,
19+
zoomButtons: true,
20+
regionsSelectable: true,
21+
markersSelectable: true,
22+
23+
regionStyle: {
24+
initial: {
25+
fill: '#e4e4e4',
26+
stroke: '#ffffff',
27+
strokeWidth: 0.5,
28+
},
29+
hover: {
30+
fill: '#2ca25f',
31+
},
32+
selected: {
33+
fill: '#1a9850',
34+
},
35+
},
36+
visualizeData: {
37+
scale: ['#C8EEFF', '#0071A4'],
38+
values: {
39+
'BR-SP': 100, // São Paulo
40+
'BR-RJ': 85, // Rio de Janeiro
41+
'BR-MG': 80, // Minas Gerais
42+
'BR-RS': 75, // Rio Grande do Sul
43+
'BR-PR': 70, // Paraná
44+
'BR-BA': 65, // Bahia
45+
},
46+
},
47+
markers: [
48+
{
49+
name: 'São Paulo',
50+
coords: [-23.5505, -46.6333],
51+
style: {
52+
fill: '#ff0000',
53+
stroke: '#ffffff',
54+
r: 5,
55+
},
56+
},
57+
],
58+
})
59+
60+
61+
62+
function toggleTheme() {
63+
isDarkTheme.value = !isDarkTheme.value
64+
options.backgroundColor = isDarkTheme.value ? '#2c3e50' : '#ffffff'
65+
if (options.regionStyle) {
66+
options.regionStyle = {
67+
...options.regionStyle,
68+
initial: {
69+
...options.regionStyle.initial,
70+
fill: isDarkTheme.value ? '#34495e' : '#e4e4e4',
71+
stroke: isDarkTheme.value ? '#1a1a1a' : '#ffffff',
72+
},
73+
}
74+
}
75+
}
76+
77+
function addRandomMarker() {
78+
// Brazil boundaries: approximately 5°S to 34°S and 34°W to 74°W
79+
const lat = -34 + Math.random() * 29 // 5°S to 34°S (negative for South)
80+
const lng = -74 + Math.random() * 40 // 34°W to 74°W (negative for West)
81+
const marker = {
82+
name: `Brazilian Marker ${(options.markers?.length ?? 0) + 1}`,
83+
coords: [lat, lng] as [number, number],
84+
style: {
85+
fill: `#${Math.floor(Math.random() * 16777215).toString(16)}`,
86+
stroke: '#ffffff',
87+
r: 5,
88+
},
89+
}
90+
options.markers = [...(options.markers || []), marker]
91+
}
92+
93+
function removeAllMarkers() {
94+
options.markers = []
95+
lastEvent.value = {
96+
type: 'All Markers Removed',
97+
time: new Date().toLocaleTimeString(),
98+
}
99+
}
100+
101+
function toggleZoom() {
102+
options.zoomOnScroll = !options.zoomOnScroll
103+
}
104+
105+
function handleRegionClick(_event: MouseEvent, code: string) {
106+
lastEvent.value = {
107+
type: 'Region Click',
108+
code,
109+
time: new Date().toLocaleTimeString(),
110+
}
111+
}
112+
113+
function handleMarkerClick(_event: MouseEvent, index: string) {
114+
lastEvent.value = {
115+
type: 'Marker Click',
116+
marker: options.markers?.[Number.parseInt(index)],
117+
time: new Date().toLocaleTimeString(),
118+
}
119+
}
120+
121+
function handleLoaded() {
122+
lastEvent.value = {
123+
type: 'Map Loaded',
124+
time: new Date().toLocaleTimeString(),
125+
}
126+
}
127+
</script>
128+
129+
<template>
130+
<div class="container">
131+
<h1>ts-maps Vue Example - Brazil Map</h1>
132+
133+
<div class="controls">
134+
<button @click="toggleTheme">
135+
Toggle Theme
136+
</button>
137+
<button @click="addRandomMarker">
138+
Add Random Marker
139+
</button>
140+
<button @click="removeAllMarkers">
141+
Remove All Markers
142+
</button>
143+
<button @click="toggleZoom">
144+
{{ options.zoomOnScroll ? 'Disable' : 'Enable' }} Zoom
145+
</button>
146+
147+
<div class="marker-info">
148+
Markers: {{ options.markers?.length || 0 }}
149+
</div>
150+
</div>
151+
152+
<div class="map-container">
153+
<Brasil
154+
:options="options"
155+
height="500px"
156+
@region-click="handleRegionClick"
157+
@marker-click="handleMarkerClick"
158+
@loaded="handleLoaded"
159+
>
160+
<template #loading>
161+
<div class="custom-loading">
162+
Loading your beautiful map...
163+
</div>
164+
</template>
165+
</Brasil>
166+
</div>
167+
168+
<div v-if="lastEvent" class="info-panel">
169+
<h3>Last Event</h3>
170+
<pre>{{ lastEvent }}</pre>
171+
</div>
172+
</div>
173+
</template>
174+
175+
<style scoped>
176+
.container {
177+
max-width: 1200px;
178+
margin: 0 auto;
179+
padding: 20px;
180+
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
181+
}
182+
183+
.controls {
184+
margin: 20px 0;
185+
padding: 20px;
186+
background: #f5f5f5;
187+
border-radius: 8px;
188+
display: flex;
189+
flex-wrap: wrap;
190+
gap: 15px;
191+
align-items: center;
192+
}
193+
194+
.control-group {
195+
display: flex;
196+
align-items: center;
197+
gap: 10px;
198+
}
199+
200+
.control-group label {
201+
font-weight: 500;
202+
}
203+
204+
.control-group select {
205+
padding: 8px;
206+
border-radius: 4px;
207+
border: 1px solid #ddd;
208+
background: white;
209+
min-width: 200px;
210+
}
211+
212+
.controls button {
213+
padding: 8px 16px;
214+
border: none;
215+
border-radius: 4px;
216+
background: #2ca25f;
217+
color: white;
218+
cursor: pointer;
219+
}
220+
221+
.controls button:hover {
222+
background: #1a9850;
223+
}
224+
225+
.map-container {
226+
border: 1px solid #ddd;
227+
border-radius: 8px;
228+
overflow: hidden;
229+
}
230+
231+
.custom-loading {
232+
display: flex;
233+
align-items: center;
234+
justify-content: center;
235+
height: 100%;
236+
background: rgba(255, 255, 255, 0.9);
237+
font-size: 1.2em;
238+
color: #666;
239+
}
240+
241+
.info-panel {
242+
margin-top: 20px;
243+
padding: 15px;
244+
background: #f9f9f9;
245+
border-radius: 8px;
246+
}
247+
248+
.control-info {
249+
padding: 8px 16px;
250+
background: #fff;
251+
border-radius: 4px;
252+
border: 1px solid #ddd;
253+
}
254+
255+
.control-info strong {
256+
color: #2ca25f;
257+
}
258+
259+
.marker-info {
260+
padding: 8px 16px;
261+
background: #fff;
262+
border-radius: 4px;
263+
border: 1px solid #ddd;
264+
font-weight: 500;
265+
color: #2ca25f;
266+
}
267+
</style>

0 commit comments

Comments
 (0)