comparison client/src/components/TimeSlider.vue @ 5036:8f421cd3c746 time-sliding

client: Implemented first version of time-sliding
author Fadi Abbud <fadi.abbud@intevation.de>
date Thu, 27 Feb 2020 09:18:17 +0100
parents
children 9d288d9b851b
comparison
equal deleted inserted replaced
4893:b65898de11ad 5036:8f421cd3c746
1 <template>
2 <div
3 id="slider"
4 :class="[
5 'd-flex box ui-element rounded bg-white mw-100 flex-row',
6 { expand: showTimeSlider }
7 ]"
8 >
9 <div
10 id="sliderContainer"
11 class="d-flex sliderContainer"
12 style="width: 98%;"
13 ></div>
14 <div @click="close" class="d-flex box-control mr-0" style="width: 2%;">
15 <font-awesome-icon icon="times"></font-awesome-icon>
16 </div>
17 </div>
18 </template>
19 <style lang="sass">
20 #slider
21 position: absolute
22 bottom: 0
23 width: 100%
24 &.expand
25 max-height: 100%;
26 max-width: 100%;
27 margin: 0
28 </style>
29 <script>
30 /* This is Free Software under GNU Affero General Public License v >= 3.0
31 * without warranty, see README.md and license for details.
32 *
33 * SPDX-License-Identifier: AGPL-3.0-or-later
34 * License-Filename: LICENSES/AGPL-3.0.txt
35 *
36 * Copyright (C) 2020 by via donau
37 * – Österreichische Wasserstraßen-Gesellschaft mbH
38 * Software engineering by Intevation GmbH
39 *
40 * Author(s):
41 * Fadi Abbud <fadiabbud@intevation.de>
42 */
43 import { mapState } from "vuex";
44 import * as d3 from "d3";
45 export default {
46 name: "timeslider",
47 data() {
48 return {
49 selectedTime: new Date("2020-01-04"),
50 newX: null
51 };
52 },
53 computed: {
54 ...mapState("application", ["showTimeSlider"])
55 },
56 methods: {
57 close() {
58 this.$store.commit("application/showTimeSlider", false);
59 },
60 createSlider() {
61 const element = document.getElementById("sliderContainer");
62 const svgWidth = element ? element.clientWidth : 0,
63 svgHeight = 40,
64 marginTop = 20,
65 marginLeft = 0;
66
67 this.newX = this.getScale();
68 let svg = d3
69 .select(".sliderContainer")
70 .append("svg")
71 .attr("width", svgWidth)
72 .attr("height", svgHeight);
73
74 // zoom event
75 let zoom = d3
76 .zoom()
77 .scaleExtent([0, Infinity])
78 .translateExtent([[0, 0], [svgWidth, svgHeight]])
79 .extent([[0, 0], [(svgWidth, svgHeight)]])
80 .on("zoom", this.zoomed);
81
82 svg
83 .append("g")
84 .attr("class", "axis--x")
85 .attr("transform", `translate(${marginLeft}, ${marginTop})`)
86 .call(
87 d3.axisBottom(this.newX).ticks(12)
88 //.tickFormat(dFormat)
89 );
90
91 // create rectanlge on the slider area to capture mouse events
92 const eventRect = svg
93 .append("rect")
94 .attr("id", "zoom")
95 .attr("class", "zoom")
96 .attr("width", svgWidth)
97 .attr("height", svgHeight)
98 .attr("fill", "white")
99 .attr("opacity", 0.2)
100 .on("mouseover", () => {
101 svg.select(".zoom").attr("cursor", "move");
102 });
103 eventRect.call(zoom).on("click", this.onClick);
104
105 const toIsoDate = d => {
106 return d.toISOString();
107 };
108
109 let drag = d3
110 .drag()
111 .on("start", () => {
112 d3.select(".line")
113 .raise()
114 .classed("active", true);
115 })
116 .on("drag", this.onDrag)
117 .on("end", () => {
118 d3.select(".line").classed("active", false);
119 });
120
121 // Create cursor to indicate to the selected time
122 svg
123 .append("rect")
124 .attr("class", "line")
125 .attr("id", "scrubber")
126 .attr("x", this.newX(d3.isoParse(toIsoDate(this.selectedTime))))
127 .attr("y", 0)
128 .attr("width", 2)
129 .attr("height", svgHeight)
130 .attr("stroke", "#17a2b8")
131 .attr("stroke-width", 2)
132 .attr("opacity", 0.6)
133 .on("mouseover", () => {
134 svg.select(".line").attr("cursor", "e-resize");
135 })
136 .call(drag);
137 },
138 getScale() {
139 return d3
140 .scaleTime()
141 .range([0, document.getElementById("sliderContainer").clientWidth || 0])
142 .domain([
143 d3.isoParse(new Date("2020-01-01")),
144 d3.isoParse(new Date("2020-03-01"))
145 ]);
146 },
147 zoomed() {
148 let scale = this.getScale();
149 this.newX = d3.event.transform.rescaleX(scale);
150 d3.select(".axis--x").call(
151 d3.axisBottom(this.newX).ticks(12)
152 //.tickFormat(dFormat)
153 );
154 d3.select(".line").attr("x", this.newX(d3.isoParse(this.selectedTime)));
155 },
156 onClick() {
157 // Extract the click location
158 let point = d3.mouse(document.getElementById("zoom")),
159 p = { x: point[0], y: point[1] };
160 d3.select(".line").attr("x", p.x);
161 this.selectedTime = d3.isoParse(this.newX.invert(p.x + 2));
162 },
163 onDrag() {
164 this.selectedTime = d3.isoParse(this.newX.invert(d3.event.x + 2));
165 d3.select(".line").attr("x", d3.event.x);
166 }
167 },
168 mounted() {
169 setTimeout(this.createSlider, 150);
170 }
171 };
172 </script>