Commit e11ed9fef9ba46f984a690b6e31ddc11cb5fcafd

Authored by 徐烜
1 parent 52b23c2b

其他公交公司用的公交电子站牌页面组件

1、新建othergj/linechart/chart目录,添加othergj-eBusStop-line-chart组件相关代码(具体参看目录下的文件)
2、新建othergj/linechart/list目录,添加othergj-eBusStop-line-chart-list组件相关代码(具体参看目录下的文件)
front-end/h5/src/components/core/plugins/bsth/mhgj/chart/css/mhgj-eBusStop-line-chart.css
@@ -142,6 +142,11 @@ svg.mhgj-eBusStop-line-chart g.part g.content6Bound text.content6_right { @@ -142,6 +142,11 @@ svg.mhgj-eBusStop-line-chart g.part g.content6Bound text.content6_right {
142 Pointer-events: none; 142 Pointer-events: none;
143 } 143 }
144 144
  145 +svg.mhgj-eBusStop-line-chart g.part path.bound2 {
  146 + stroke: rgb(0, 0, 0);
  147 + stroke-width: 1;
  148 + stroke-dasharray: 4,2;
  149 +}
145 svg.mhgj-eBusStop-line-chart g.part g.content7Bound1 { 150 svg.mhgj-eBusStop-line-chart g.part g.content7Bound1 {
146 } 151 }
147 svg.mhgj-eBusStop-line-chart g.part g.content7Bound1 text.content7_1_left { 152 svg.mhgj-eBusStop-line-chart g.part g.content7Bound1 text.content7_1_left {
front-end/h5/src/components/core/plugins/bsth/mhgj/chart/mhgj-eBusStop-line-chart.js
@@ -1472,7 +1472,27 @@ export default { @@ -1472,7 +1472,27 @@ export default {
1472 } 1472 }
1473 }) 1473 })
1474 // ------------ 3-2-4、当part3存在时,part2纵向中间右侧添加内容(以上)----------- // 1474 // ------------ 3-2-4、当part3存在时,part2纵向中间右侧添加内容(以上)----------- //
1475 - // ------------ 3-2-5、当part3不存在时,part2添加内容(以下)----------- // 1475 + // ------------ 3-2-5、当part3不存在时,part2中间纵向添加一条虚线(以下)---------- //
  1476 + let boundLineFun2 = d3.line()
  1477 + itemsEnter.select(function (d) {
  1478 + return d.svgPartIndex === 2 && showType === 2 ? this : null
  1479 + }).append('path')
  1480 + .classed('bound2', true)
  1481 + .attr('d', function () {
  1482 + return boundLineFun2([
  1483 + [partWidth, partTitleRectHeight],
  1484 + [partWidth, partHeight]
  1485 + ])
  1486 + })
  1487 + itemsUpdate.select('path.bound2')
  1488 + .attr('d', function () {
  1489 + return boundLineFun2([
  1490 + [partWidth, partTitleRectHeight],
  1491 + [partWidth, partHeight]
  1492 + ])
  1493 + })
  1494 + // ------------ 3-2-5、当part3不存在时,part2中间纵向添加一条虚线(以上)---------- //
  1495 + // ------------ 3-2-6、当part3不存在时,part2添加内容(以下)----------- //
1476 itemsEnter.select(function (d) { 1496 itemsEnter.select(function (d) {
1477 return d.svgPartIndex === 2 && showType === 2 ? this : null 1497 return d.svgPartIndex === 2 && showType === 2 ? this : null
1478 }).append('g') 1498 }).append('g')
@@ -1654,7 +1674,7 @@ export default { @@ -1654,7 +1674,7 @@ export default {
1654 return `translate(${dx}, ${dy})` 1674 return `translate(${dx}, ${dy})`
1655 } 1675 }
1656 }) 1676 })
1657 - // ------------ 3-2-5、当part3不存在时,part2添加内容(以上)----------- // 1677 + // ------------ 3-2-6、当part3不存在时,part2添加内容(以上)----------- //
1658 1678
1659 // ------------ 3-3、part3部分 -------------// 1679 // ------------ 3-3、part3部分 -------------//
1660 itemsEnter.select(function (d) { 1680 itemsEnter.select(function (d) {
front-end/h5/src/components/core/plugins/bsth/othergj/linechart/chart/bak.js deleted 100644 → 0
1 -/**  
2 - * 自定义线路模拟图组件  
3 - */  
4 -import PropTypes from '@luban-h5/plugin-common-props'  
5 -  
6 -import Utils from 'core/plugins/bsth/bsth-utils'  
7 -import { OgEBusStopData } from 'core/plugins/bsth/othergj/linechart/chart/models/OgEBusStopData'  
8 -  
9 -import './css/othergj-eBusStop-line-chart.css'  
10 -  
11 -import moment from 'moment'  
12 -  
13 -export default {  
14 - extra: {  
15 - defaultStyle: { // 默认属性  
16 - top: 0,  
17 - left: 0,  
18 - width: 700,  
19 - height: 230  
20 - }  
21 - },  
22 - name: 'othergj-eBusStop-line-chart',  
23 - data () {  
24 - this.private_svgns = 'http://www.w3.org/2000/svg' // svg元素名字空间  
25 - this.private_svg = null // 创建的根svg元素,由mounted钩子函数创建  
26 - // eslint-disable-next-line  
27 - this.private_jQuery = jQuery.noConflict() // jquery引用  
28 - // eslint-disable-next-line  
29 - this.private_d3 = d3 // d3引用  
30 -  
31 - return {  
32 - /**  
33 - * 监控外层元素的宽度高度变化  
34 - * 1、由于编辑器缩放,自定义组件无法监控,所以需要定义一个定时器监控最外层元素的大小变化  
35 - * 2、建议所有自定义组件,最外层都定义一个div包在自定义组件最外层,不要关联任何自定义的属性,样式对应编辑器的通用样式  
36 - */  
37 - watchWidthHeightTimer: {  
38 - timer: null,  
39 - count: 0,  
40 - millisecond: 1000  
41 - },  
42 -  
43 - // TODO:其他timer  
44 -  
45 - // 注意:css里设定了box-sizing: border-box;,所以组件本身的宽高包括了margin,padding,border  
46 - // 所以计算内部其他组件宽高需要减去margin,padding,border  
47 - component_width: 350, // 组件宽度  
48 - component_height: 400, // 组件高度  
49 - svg_width: 350, // svg图宽度  
50 - svg_height: 300, // svg图高度  
51 -  
52 - // TODO:其他属性  
53 -  
54 - // svg内部下部分线的属性(mounted初始计算一次)  
55 - down_line_x1: 0,  
56 - down_line_y1: 0,  
57 - down_line_x2: 0,  
58 - down_line_y2: 0,  
59 - down_line_x3: 0,  
60 - down_line_y3: 0,  
61 - down_line_x4: 0,  
62 - down_line_y4: 0,  
63 - down_line_x5: 0,  
64 - down_line_y5: 0,  
65 -  
66 - eBusStopData: null // 电子站牌数据(EBusStopData类型)  
67 - }  
68 -  
69 - },  
70 - computed: {  
71 - // TODO:其他计算属性  
72 - },  
73 - prop: {  
74 - useMode: PropTypes.string({ // 自定义使用模式,alone:(单独使用),child:(子组件)  
75 - defaultValue: 'alone',  
76 - label: '使用模式',  
77 - visible: false  
78 - }),  
79 - editorMode: PropTypes.string({ // 编辑模式会由编辑器自动注入(值:edit, preview)  
80 - defaultValue: 'edit',  
81 - label: '模式',  
82 - visible: false  
83 - }),  
84 - line_chart_outer_div_width: PropTypes.number({  
85 - defaultValue: 350,  
86 - label: 'line-chart-outer-div样式的div宽度',  
87 - visible: false  
88 - }),  
89 - line_chart_outer_div_height: PropTypes.number({  
90 - defaultValue: 300,  
91 - label: 'line-chart-outer-div样式的div高度',  
92 - visible: false  
93 - }),  
94 - eBusStopData_child: { // 作为子组件,父对象传值  
95 - type: OgEBusStopData,  
96 - default: function () {  
97 - return null  
98 - }  
99 - },  
100 -  
101 - // 数据属性  
102 - _flag_1_: PropTypes.string({ label: '', component: null, extra: function (h) { return (<hr data-label="数据属性" class="bsth-line-item-divider"></hr>) } }),  
103 - // 图外层css  
104 - _flag_2_: PropTypes.string({ label: '', component: null, extra: function (h) { return (<hr data-label="图外层css属性" class="bsth-line-item-divider"></hr>) } }),  
105 - margin_left: PropTypes.number({ label: '图左边margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),  
106 - margin_right: PropTypes.number({ label: '图右边margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),  
107 - margin_top: PropTypes.number({ label: '图上边margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),  
108 - margin_bottom: PropTypes.number({ label: '图底部margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),  
109 - border_size: PropTypes.number({ label: '图边框宽度', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),  
110 - background_color: PropTypes.color({ label: '背景颜色', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }),  
111 - // TODO:其他flag  
112 - _flag_5_: PropTypes.string({ label: '', component: null, extra: function (h) { return (<hr data-label="图内层线路图css属性" class="bsth-line-item-divider"></hr>) } }),  
113 - svg_background: PropTypes.color({ label: '线路图背景颜色', defaultValue: '#9EE0DF', layout: { prefixCls: 'bsth-line' } }),  
114 - chart_left_padding: PropTypes.number({ label: '内部线路图距离左边', defaultValue: 50, layout: { prefixCls: 'bsth-line' } }),  
115 - chart_right_padding: PropTypes.number({ label: '内部线路图距离右边', defaultValue: 50, layout: { prefixCls: 'bsth-line' } }),  
116 - chart_top_padding: PropTypes.number({ label: '内部线路图距离上边', defaultValue: 13, layout: { prefixCls: 'bsth-line' } }),  
117 - chart_up_line_path_s_width: PropTypes.number({ label: '上部分线宽度', defaultValue: 5, layout: { prefixCls: 'bsth-line' } }),  
118 - chart_up_line_path_s_color: PropTypes.color({ label: '上部分线颜色', defaultValue: '#008000', layout: { prefixCls: 'bsth-line' } }),  
119 - chart_up_line_circle_f_color_current: PropTypes.color({ label: '线圆圈填充色-当前站点', defaultValue: '#CB0808', layout: { prefixCls: 'bsth-line' } }),  
120 - chart_up_line_circle_f_color_before: PropTypes.color({ label: '线圆圈填充色-前面站点', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }),  
121 - chart_up_line_circle_f_color_after: PropTypes.color({ label: '线圆圈填充色-后面站点', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }),  
122 - chart_up_line_circle_r: PropTypes.number({ label: '线圆圈大小', defaultValue: 8, layout: { prefixCls: 'bsth-line' } }),  
123 - chart_station_text_top_padding: PropTypes.number({ label: '站点文字距离上边', defaultValue: 30, layout: { prefixCls: 'bsth-line' } }),  
124 - chart_station_text_font_size_current: PropTypes.number({ label: '站名字体大小-当前站点', defaultValue: 25, layout: { prefixCls: 'bsth-line' } }),  
125 - chart_station_text_font_size_before: PropTypes.number({ label: '站名字体大小-前面站点', defaultValue: 20, layout: { prefixCls: 'bsth-line' } }),  
126 - chart_station_text_font_size_after: PropTypes.number({ label: '站名字体大小-后面站点', defaultValue: 20, layout: { prefixCls: 'bsth-line' } }),  
127 - chart_station_text_length: PropTypes.number({ label: '站名长度', defaultValue: 100, layout: { prefixCls: 'bsth-line' } }),  
128 - chart_up_station_text_font_f_color_current: PropTypes.color({ label: '站名颜色-当前站点', defaultValue: '#060D37', layout: { prefixCls: 'bsth-line' } }),  
129 - chart_up_station_text_font_f_color_before: PropTypes.color({ label: '站名颜色-前面站点', defaultValue: '#9398B4', layout: { prefixCls: 'bsth-line' } }),  
130 - chart_up_station_text_font_f_color_after: PropTypes.color({ label: '站名颜色-后面站点', defaultValue: '#4556b6', layout: { prefixCls: 'bsth-line' } }),  
131 - _flag_6_: PropTypes.string({ label: '', component: null, extra: function (h) { return (<hr data-label="图内层下部分线css属性" class="bsth-line-item-divider"></hr>) } }),  
132 - down_line_left_padding: PropTypes.number({ label: '线距离左边', defaultValue: 20, layout: { prefixCls: 'bsth-line' } }),  
133 - down_line_right_padding: PropTypes.number({ label: '线距离右边', defaultValue: 20, layout: { prefixCls: 'bsth-line' } }),  
134 - down_line_bottom_padding: PropTypes.number({ label: '线距离下边', defaultValue: 6, layout: { prefixCls: 'bsth-line' } }),  
135 - down_line_s_width: PropTypes.number({ label: '线宽度', defaultValue: 5, layout: { prefixCls: 'bsth-line' } }),  
136 - down_line_s_color: PropTypes.color({ label: '线颜色', defaultValue: '#277461', layout: { prefixCls: 'bsth-line' } }),  
137 - down_line_arrow_width: PropTypes.number({ label: '箭头宽度', defaultValue: 55, layout: { prefixCls: 'bsth-line' } }),  
138 - down_line_arrow_height: PropTypes.number({ label: '箭头高度', defaultValue: 15, layout: { prefixCls: 'bsth-line' } }),  
139 - _flag_7_: PropTypes.string({ label: '', component: null, extra: function (h) { return (<hr data-label="无数据提示css属性" class="bsth-line-item-divider"></hr>) } }),  
140 - empty_info_font_size: PropTypes.number({ label: '无数据提示文字字体大小', defaultValue: 30, layout: { prefixCls: 'bsth-line' } }),  
141 - empty_info_font_color: PropTypes.color({ label: '无数据提示文字字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } }),  
142 - empty_info_top_padding: PropTypes.number({ label: '无数据提示文字距离上边', defaultValue: 25, layout: { prefixCls: 'bsth-line' } })  
143 - },  
144 -  
145 - render () {  
146 - const innerDivStyle = {  
147 - 'width': this.component_width + 'px',  
148 - 'height': this.component_height + 'px',  
149 - 'border': this.border_size + 'px solid black',  
150 - 'margin-left': this.margin_left + 'px',  
151 - 'margin-right': this.margin_right + 'px',  
152 - 'margin-top': this.margin_top + 'px',  
153 - 'margin-bottom': this.margin_bottom + 'px',  
154 - 'background': this.background_color,  
155 - 'position': 'relative'  
156 - }  
157 -  
158 - const downLinePathD =  
159 - 'M' + this.down_line_x1 + ' ' + this.down_line_y1 + ' ' +  
160 - 'L' + this.down_line_x2 + ' ' + this.down_line_y2 + ' ' +  
161 - 'L' + this.down_line_x3 + ' ' + this.down_line_y3 + ' ' +  
162 - 'L' + this.down_line_x4 + ' ' + this.down_line_y4 + ' ' +  
163 - 'L' + this.down_line_x5 + ' ' + this.down_line_y5 + ' ' +  
164 - 'Z'  
165 -  
166 - const svgStyle = {  
167 - // 'width': this.line_width + 'px',  
168 - 'height': this.svg_height + 'px',  
169 - 'background-color': this.svg_background  
170 - }  
171 -  
172 - const emptyInfoStyle = {  
173 - 'height': '44px',  
174 - 'position': 'absolute',  
175 - 'left': '50%',  
176 - 'transform': 'translate(-50%, 0)',  
177 - '-webkit-transform': 'translate(-50%, 0)',  
178 - 'color': this.empty_info_font_color,  
179 - 'font-size': this.empty_info_font_size + 'px',  
180 - 'padding-top': this.empty_info_top_padding + 'px',  
181 - // 'font-family': 'Open Sans, sans-serif',  
182 - 'font-weight': 'bold'  
183 - }  
184 -  
185 - /* 最外层div对应编辑器的通用样式 */  
186 - return (  
187 - <div class="othergj-eBusStop-line-chart-outer-div">  
188 - <div style={innerDivStyle}>  
189 - <svg class="othergj-eBusStop-line-chart"  
190 - data-code={this.eBusStopData.lineCode}  
191 - style={svgStyle}>  
192 - <g class="arrow-wrap">  
193 - <path d={downLinePathD} style={{ 'fill': this.down_line_s_color }}></path>  
194 - </g>  
195 - </svg>  
196 - {  
197 - this.eBusStopData.routeStationDataList.length === 0 ? (<div style={emptyInfoStyle}>线路未开通,系统调试中</div>) : ''  
198 - }  
199 - </div>  
200 - </div>  
201 - )  
202 -  
203 - },  
204 - beforeMount () {  
205 - // 设置数据  
206 - if (this.useMode === 'alone') { // 单独使用,使用测试数据  
207 - this.eBusStopData = OgEBusStopData.generateTestData()  
208 - } else { // 自组件使用,使用父组件传值  
209 - this.eBusStopData = this.eBusStopData_child  
210 - }  
211 - },  
212 - mounted () {  
213 - // svg元素  
214 - this.private_svg = this.findD3SvgDom()  
215 - // this.private_up_rect_wrap_svg = this.findD3UpRectWrapSvg()  
216 -  
217 - // 使用外部元素的框架定义图的长宽  
218 - let $jQuery = this.private_jQuery  
219 - this.component_width = $jQuery(this.$el).width() - this.margin_left - this.margin_right  
220 - this.component_height = $jQuery(this.$el).height() - this.margin_top - this.margin_bottom  
221 -  
222 - if (this.useMode === 'child') {  
223 - this.component_width = this.line_chart_outer_div_width - this.margin_left - this.margin_right  
224 - this.component_height = this.line_chart_outer_div_height - this.margin_top - this.margin_bottom  
225 - }  
226 -  
227 - // 开启外部元素长宽监控计数  
228 - /**  
229 - * 开启外部元素长宽监控逻辑(class='line-chart-outer-div')  
230 - * 1、使用模式是alone,并且是编辑模式edit  
231 - * 2、preview预览模式下有条件监控  
232 - */  
233 - if (this.useMode === 'alone' && this.editorMode === 'edit') {  
234 - this.watchWidthHeightTimer.count++  
235 - }  
236 -  
237 - // 刷新线路svg  
238 - this.refreshLineSvg()  
239 - // 刷新下部分线svg  
240 - this.refreshDownLineSvg()  
241 - },  
242 - destroyed () {  
243 - // 组件删除的时候,删除监控定时器  
244 - let timer = this.watchWidthHeightTimer.timer  
245 - if (timer) {  
246 - clearTimeout(timer)  
247 - this.watchWidthHeightTimer.timer = null  
248 - }  
249 - // TODO:其他timer  
250 - },  
251 - watch: {  
252 - 'watchWidthHeightTimer.count' () { // 定时器监控  
253 - let timer = this.watchWidthHeightTimer.timer  
254 - if (timer) {  
255 - clearTimeout(timer)  
256 - this.watchWidthHeightTimer.timer = null  
257 - }  
258 -  
259 - let self = this  
260 - let $jQuery = this.private_jQuery  
261 - self.watchWidthHeightTimer.timer = setTimeout(function () {  
262 - // 处理逻辑  
263 - let width = $jQuery(self.$el).width()  
264 - let height = $jQuery(self.$el).height()  
265 -  
266 - if (width !== self.component_width) {  
267 - self.component_width = width - self.margin_left - self.margin_right  
268 - }  
269 - if (height !== self.component_height) {  
270 - self.component_height = height - self.margin_top - self.margin_bottom  
271 - }  
272 - self.watchWidthHeightTimer.count++  
273 - }, self.watchWidthHeightTimer.millisecond)  
274 - },  
275 - // /**  
276 - // * 当组件作为子组件使用时(useMode=child),line-chart-outer-div样式的div尺寸无法通过编辑器改变(通用样式)  
277 - // * 必须由父组件设定,自组件需要监控改变  
278 - // */  
279 - // line_chart_outer_div_width: function (val) {  
280 - // let self = this  
281 - // if (self.useMode === 'child') {  
282 - // self.component_width = val - self.margin_left - self.margin_right  
283 - // }  
284 - // },  
285 - // line_chart_outer_div_height: function (val) {  
286 - // let self = this  
287 - // if (self.useMode === 'child') {  
288 - // self.component_height = val - self.margin_top - self.margin_bottom  
289 - // }  
290 - // },  
291 - // eBusStopData_child: function (val) {  
292 - // let self = this  
293 - // if (self.useMode === 'child') {  
294 - // self.eBusStopData_child = val  
295 - // }  
296 - // },  
297 - // // ----------- 数据属性 ----------- //  
298 - // eBusStopData: function (currentVal, oldVal) {  
299 - // let self = this  
300 - // if (!Utils.objectEquals(currentVal, oldVal)) {  
301 - // self.refreshLineSvg()  
302 - // }  
303 - // },  
304 - //  
305 - // // ------------ 本身宽高 ----------- //  
306 - // component_width () {  
307 - // this.text_info_width = this.component_width - this.border_size * 2  
308 - // this.line_width = this.component_width - this.border_size * 2  
309 - // },  
310 - // component_height () {  
311 - // this.text_info_height = this.line_info_height + this.arrive_info_height  
312 - // this.line_height = this.component_height - this.text_info_height - this.border_size * 2  
313 - // },  
314 - //  
315 - // svg_width () {  
316 - // this.refreshLineSvg()  
317 - // this.refreshDownLineSvg()  
318 - // },  
319 - // svg_height () {  
320 - // this.refreshLineSvg()  
321 - // this.refreshDownLineSvg()  
322 - // },  
323 - //  
324 - // // ----------- 图外层css 监控 ----------- //  
325 - // margin_left () {  
326 - // let self = this  
327 - // self.component_width = self.component_width - self.margin_left - self.margin_right  
328 - // },  
329 - // margin_right () {  
330 - // let self = this  
331 - // self.component_width = self.component_width - self.margin_left - self.margin_right  
332 - // },  
333 - // margin_top () {  
334 - // let self = this  
335 - // self.component_height = self.component_height - self.margin_top - self.margin_bottom  
336 - // },  
337 - // margin_bottom () {  
338 - // let self = this  
339 - // self.component_height = self.component_height - self.margin_top - self.margin_bottom  
340 - // },  
341 - // border_size () {  
342 - // this.text_info_width = this.component_width - this.border_size * 2  
343 - // this.line_width = this.component_width - this.border_size * 2  
344 - // this.text_info_height = this.line_info_height + this.arrive_info_height  
345 - // this.line_height = this.component_height - this.text_info_height - this.border_size * 2  
346 - //  
347 - // },  
348 - //  
349 - // // ----------- 图内层css 监控 ----------- //  
350 - // // ----------- _flag_5_属性 ----------//  
351 - // chart_left_padding: function () {  
352 - // this.refreshLineSvg()  
353 - // },  
354 - // chart_right_padding: function () {  
355 - // this.refreshLineSvg()  
356 - // },  
357 - // chart_top_padding: function () {  
358 - // this.refreshLineSvg()  
359 - // },  
360 - // chart_up_line_path_s_width: function (val) {  
361 - // let svg = this.private_svg  
362 - // svg.selectAll('g.item path.station_link:not(.down)')  
363 - // .style('stroke-width', val)  
364 - // },  
365 - // chart_up_line_path_s_color: function (val) {  
366 - // let svg = this.private_svg  
367 - // svg.selectAll('g.item path.station_link:not(.down)')  
368 - // .style('stroke', val)  
369 - // },  
370 - // chart_up_line_circle_f_color_current: function (val) {  
371 - // let svg = this.private_svg  
372 - // svg.selectAll('g.item circle.station_circle.current')  
373 - // .style('fill', val)  
374 - // },  
375 - // chart_up_line_circle_f_color_before: function (val) {  
376 - // let svg = this.private_svg  
377 - // svg.selectAll('g.item circle.station_circle.before')  
378 - // .style('fill', val)  
379 - // },  
380 - // chart_up_line_circle_f_color_after: function (val) {  
381 - // let svg = this.private_svg  
382 - // svg.selectAll('g.item circle.station_circle.after')  
383 - // .style('fill', val)  
384 - // },  
385 - // chart_up_line_circle_r: function (val) {  
386 - // let svg = this.private_svg  
387 - // svg.selectAll('g.item circle.station_circle')  
388 - // .style('r', val)  
389 - // },  
390 - // chart_station_text_top_padding: function (val) {  
391 - // this.refreshLineSvg()  
392 - // },  
393 - // chart_station_text_font_size_current: function (val) {  
394 - // let svg = this.private_svg  
395 - // svg.selectAll('g.item text.station_text.up.current')  
396 - // .style('font-size', val)  
397 - // },  
398 - // chart_station_text_font_size_before: function (val) {  
399 - // let svg = this.private_svg  
400 - // svg.selectAll('g.item text.station_text.up.before')  
401 - // .style('font-size', val)  
402 - // },  
403 - // chart_station_text_font_size_after: function (val) {  
404 - // let svg = this.private_svg  
405 - // svg.selectAll('g.item text.station_text.up.after')  
406 - // .style('font-size', val)  
407 - // },  
408 - // chart_station_text_length: function (val) {  
409 - // let svg = this.private_svg  
410 - // svg.selectAll('g.item text')  
411 - // .attr('textLength', val)  
412 - // },  
413 - // chart_up_station_text_font_f_color_current: function (val) {  
414 - // let svg = this.private_svg  
415 - // svg.selectAll('g.item text.station_text.up.current')  
416 - // .style('stroke', val)  
417 - // },  
418 - // chart_up_station_text_font_f_color_before: function (val) {  
419 - // let svg = this.private_svg  
420 - // svg.selectAll('g.item text.station_text.up.before')  
421 - // .style('stroke', val)  
422 - // },  
423 - // chart_up_station_text_font_f_color_after: function (val) {  
424 - // let svg = this.private_svg  
425 - // svg.selectAll('g.item text.station_text.up.after')  
426 - // .style('stroke', val)  
427 - // },  
428 - // // ----------- _flag_6_属性 ----------//  
429 - // down_line_left_padding: function () {  
430 - // this.refreshDownLineSvg()  
431 - // },  
432 - // down_line_right_padding: function () {  
433 - // this.refreshDownLineSvg()  
434 - // },  
435 - // down_line_bottom_padding: function () {  
436 - // this.refreshDownLineSvg()  
437 - // },  
438 - // down_line_s_width: function () {  
439 - // this.refreshDownLineSvg()  
440 - // },  
441 - // down_line_arrow_width: function () {  
442 - // this.refreshDownLineSvg()  
443 - // },  
444 - // down_line_arrow_height: function () {  
445 - // this.refreshDownLineSvg()  
446 - // }  
447 - // ----------- _flag_7_属性 ----------//  
448 - // TODO:  
449 - },  
450 - methods: {  
451 - findD3SvgDom () {  
452 - let $jQuery = this.private_jQuery  
453 - let d3 = this.private_d3  
454 - let svgDom = $jQuery(this.$el).find('svg')[0]  
455 - return d3.select(svgDom)  
456 - },  
457 -  
458 - refreshDownLineSvg () {  
459 - let self = this  
460 -  
461 - let width = self.svg_width // 内部整个svg的宽度  
462 - let height = self.svg_height // 内部整个svg的高度  
463 -  
464 - // 计算svg内部下部分线的属性  
465 - // 5个点,左边两个点作为起点(两个起点用来模拟宽度,如果使用stroke-width,右边箭头无法是夹的),右边3个点组成半个箭头  
466 - // 最左边起点(左下)  
467 - this.down_line_x1 = self.down_line_left_padding  
468 - this.down_line_y1 = height - self.down_line_bottom_padding  
469 - // 最右边箭头起点  
470 - this.down_line_x2 = width - self.down_line_right_padding  
471 - this.down_line_y2 = this.down_line_y1  
472 - // 箭头左上角  
473 - this.down_line_x3 = this.down_line_x2 - self.down_line_arrow_width  
474 - this.down_line_y3 = this.down_line_y2 - self.down_line_arrow_height - self.down_line_s_width  
475 - // 箭头左下角  
476 - this.down_line_x4 = this.down_line_x3  
477 - this.down_line_y4 = this.down_line_y2 - self.down_line_s_width  
478 - // 最左边起点(右下)  
479 - this.down_line_x5 = this.down_line_x1  
480 - this.down_line_y5 = this.down_line_y4  
481 - },  
482 -  
483 - refreshLineSvg () {  
484 - let self = this  
485 -  
486 - // let $jQuery = self.private_jQuery  
487 - let d3 = self.private_d3  
488 -  
489 - let routeData = self.eBusStopData.routeStationDataList  
490 - let width = self.svg_width // 内部整个svg的宽度  
491 - // let height = self.line_height // 内部整个svg的高度  
492 - // let svgNameSpace = self.private_svgns  
493 - let svg = self.private_svg  
494 - let chartLeftPadding = self.chart_left_padding  
495 - let chartRightPadding = self.chart_right_padding  
496 - let chartTopPadding = self.chart_top_padding  
497 - let chartStopNameTopPadding = self.chart_station_text_top_padding  
498 -  
499 - // ------------ 1、添加g元素 ---------- //  
500 - let itemsUpdate = svg.selectAll('g.item')  
501 - .data(routeData, function (d) {  
502 - return d.code  
503 - })  
504 - let itemsEnter = itemsUpdate  
505 - let itemsExit = itemsUpdate.exit()  
506 -  
507 - itemsExit.remove()  
508 - itemsEnter = itemsEnter.enter().append('g').classed('item', true)  
509 -  
510 - // 创建x轴比例尺  
511 - let xScale = d3.scaleLinear()  
512 - .domain([0, routeData.length - 1]) // 定义域  
513 - .range([chartLeftPadding, width - chartRightPadding]) // 值域  
514 -  
515 - // ------------ 2、添加/更新线路图上部分的的path元素 ---------- //  
516 - let upLineFun = d3.line()  
517 - .x(xScale)  
518 - .y(function () {  
519 - return chartTopPadding  
520 - })  
521 - itemsEnter.append('path')  
522 - .classed('station_link', true)  
523 - .style('stroke', self.chart_up_line_path_s_color)  
524 - .style('stroke-width', self.chart_up_line_path_s_width)  
525 - .attr('d', function (d, i) {  
526 - return i < routeData.length - 1 ? upLineFun([i, i + 1]) : ''  
527 - })  
528 - itemsUpdate.select('path')  
529 - .attr('d', function (d, i) {  
530 - return i < routeData.length - 1 ? upLineFun([i, i + 1]) : ''  
531 - })  
532 -  
533 - // ------------ 3、添加/更新线路图上部分的circle元素 ---------- //  
534 - itemsEnter.select(function (d) {  
535 - return d.type !== 1 ? this : null  
536 - }).append('circle')  
537 - .classed('station_circle', true)  
538 - .classed('current', function (d, i) {  
539 - return self.eBusStopData.currentStopStationIndex === i  
540 - })  
541 - .classed('before', function (d, i) {  
542 - return i < self.eBusStopData.currentStopStationIndex  
543 - })  
544 - .classed('after', function (d, i) {  
545 - return i > self.eBusStopData.currentStopStationIndex  
546 - })  
547 - .style('fill', function (d, i) {  
548 - if (i === self.eBusStopData.currentStopStationIndex) {  
549 - return self.chart_up_line_circle_f_color_current  
550 - } else if (i < self.eBusStopData.currentStopStationIndex) {  
551 - return self.chart_up_line_circle_f_color_before  
552 - } else {  
553 - return self.chart_up_line_circle_f_color_after  
554 - }  
555 - })  
556 - .style('stroke-width', 0) // 暂时外部的stroke设置为0,不参与属性设置  
557 - .attr('r', self.chart_up_line_circle_r) // css也设置了,但是有些游览器不支持(如 android5.1的内置游览器),所以直接定义成属性  
558 - .attr('cx', function (d, i) {  
559 - return xScale(i)  
560 - })  
561 - .attr('cy', function () {  
562 - return chartTopPadding  
563 - })  
564 - .attr('data-id', function (d) {  
565 - return d.code  
566 - })  
567 - itemsUpdate.select('circle')  
568 - .attr('cx', function (d, i) {  
569 - return xScale(i)  
570 - })  
571 - .attr('cy', function () {  
572 - return chartTopPadding  
573 - })  
574 -  
575 - // ------------ 4、添加/更新线路图上部分的站点名称text元素 ---------- //  
576 - itemsEnter.append('text')  
577 - .classed('station_text', true)  
578 - .classed('up', true)  
579 - .classed('current', function (d, i) {  
580 - return self.eBusStopData.currentStopStationIndex === i  
581 - })  
582 - .classed('before', function (d, i) {  
583 - return i < self.eBusStopData.currentStopStationIndex  
584 - })  
585 - .classed('after', function (d, i) {  
586 - return i > self.eBusStopData.currentStopStationIndex  
587 - })  
588 - .style('font-size', function (d, i) {  
589 - if (i === self.eBusStopData.currentStopStationIndex) {  
590 - return self.chart_station_text_font_size_current + 'px'  
591 - } else if (i < self.eBusStopData.currentStopStationIndex) {  
592 - return self.chart_station_text_font_size_before + 'px'  
593 - } else {  
594 - return self.chart_station_text_font_size_after + 'px'  
595 - }  
596 - })  
597 - .style('stroke', function (d, i) {  
598 - if (i === self.eBusStopData.currentStopStationIndex) {  
599 - return self.chart_up_station_text_font_f_color_current  
600 - } else if (i < self.eBusStopData.currentStopStationIndex) {  
601 - return self.chart_up_station_text_font_f_color_before  
602 - } else {  
603 - return self.chart_up_station_text_font_f_color_after  
604 - }  
605 - })  
606 - .attr('textLength', self.chart_station_text_length)  
607 - .text(function (d) {  
608 - if (!d.name) {  
609 - return 0  
610 - }  
611 - return d.name  
612 - })  
613 - .attr('title', function (d) {  
614 - return d.name  
615 - })  
616 - .attr('x', function (d, i) {  
617 - return xScale(i)  
618 - })  
619 - .attr('y', function (d) {  
620 - return chartStopNameTopPadding  
621 - })  
622 - itemsUpdate.select('text.station_text')  
623 - .classed('up', true)  
624 - .text(function (d) {  
625 - if (!d.name) {  
626 - return 0  
627 - }  
628 - return d.name  
629 - })  
630 - .attr('title', function (d) {  
631 - return d.name  
632 - })  
633 - .attr('x', function (d, i) {  
634 - return xScale(i)  
635 - })  
636 - .attr('y', function (d) {  
637 - return chartStopNameTopPadding  
638 - })  
639 - }  
640 - }  
641 -  
642 -}  
643 -  
644 -  
645 -  
646 -  
647 -  
648 -  
649 -  
front-end/h5/src/components/core/plugins/bsth/othergj/linechart/chart/models/eBusStopData.js
@@ -116,9 +116,9 @@ class EBusStopData { @@ -116,9 +116,9 @@ class EBusStopData {
116 */ 116 */
117 static generateTestData () { 117 static generateTestData () {
118 // 1、站点信息 118 // 1、站点信息
119 - let s1 = new StationData('站点1', '1') 119 + let s1 = new StationData('站点1的名字非常长', '1')
120 let s2 = new StationData('站点2', '2') 120 let s2 = new StationData('站点2', '2')
121 - let s3 = new StationData('站点3', '3') 121 + let s3 = new StationData('站点3也非常长也非常长也非常长', '3')
122 let s4 = new StationData('站点4', '4') 122 let s4 = new StationData('站点4', '4')
123 let s5 = new StationData('站点5', '5') 123 let s5 = new StationData('站点5', '5')
124 let s6 = new StationData('站点6', '6') 124 let s6 = new StationData('站点6', '6')
front-end/h5/src/components/core/plugins/bsth/othergj/linechart/chart/othergj-eBusStop-line-chart.js
@@ -41,6 +41,15 @@ export default { @@ -41,6 +41,15 @@ export default {
41 millisecond: 1000 41 millisecond: 1000
42 }, 42 },
43 43
  44 + /**
  45 + * 监控svgText坐标变化
  46 + */
  47 + svgTextTransformPositionTimer: {
  48 + timer: null,
  49 + count: 0,
  50 + millisecond: 500
  51 + },
  52 +
44 // TODO:其他timer 53 // TODO:其他timer
45 54
46 // 注意:css里设定了box-sizing: border-box;,所以组件本身的宽高包括了margin,padding,border 55 // 注意:css里设定了box-sizing: border-box;,所以组件本身的宽高包括了margin,padding,border
@@ -77,7 +86,7 @@ export default { @@ -77,7 +86,7 @@ export default {
77 visible: false 86 visible: false
78 }), 87 }),
79 editorMode: PropTypes.string({ // 编辑模式会由编辑器自动注入(值:edit, preview) 88 editorMode: PropTypes.string({ // 编辑模式会由编辑器自动注入(值:edit, preview)
80 - defaultValue: 'edit', 89 + defaultValue: 'preview',
81 label: '模式', 90 label: '模式',
82 visible: false 91 visible: false
83 }), 92 }),
@@ -113,18 +122,19 @@ export default { @@ -113,18 +122,19 @@ export default {
113 svg_background: PropTypes.color({ label: '线路图背景颜色', defaultValue: '#9EE0DF', layout: { prefixCls: 'bsth-line' } }), 122 svg_background: PropTypes.color({ label: '线路图背景颜色', defaultValue: '#9EE0DF', layout: { prefixCls: 'bsth-line' } }),
114 chart_left_padding: PropTypes.number({ label: '内部线路图距离左边', defaultValue: 50, layout: { prefixCls: 'bsth-line' } }), 123 chart_left_padding: PropTypes.number({ label: '内部线路图距离左边', defaultValue: 50, layout: { prefixCls: 'bsth-line' } }),
115 chart_right_padding: PropTypes.number({ label: '内部线路图距离右边', defaultValue: 50, layout: { prefixCls: 'bsth-line' } }), 124 chart_right_padding: PropTypes.number({ label: '内部线路图距离右边', defaultValue: 50, layout: { prefixCls: 'bsth-line' } }),
116 - chart_top_padding: PropTypes.number({ label: '内部线路图距离上边', defaultValue: 13, layout: { prefixCls: 'bsth-line' } }), 125 + chart_top_padding: PropTypes.number({ label: '内部线路图距离上边', defaultValue: 40, layout: { prefixCls: 'bsth-line' } }),
117 chart_up_line_path_s_width: PropTypes.number({ label: '上部分线宽度', defaultValue: 5, layout: { prefixCls: 'bsth-line' } }), 126 chart_up_line_path_s_width: PropTypes.number({ label: '上部分线宽度', defaultValue: 5, layout: { prefixCls: 'bsth-line' } }),
118 chart_up_line_path_s_color: PropTypes.color({ label: '上部分线颜色', defaultValue: '#008000', layout: { prefixCls: 'bsth-line' } }), 127 chart_up_line_path_s_color: PropTypes.color({ label: '上部分线颜色', defaultValue: '#008000', layout: { prefixCls: 'bsth-line' } }),
119 chart_up_line_circle_f_color_current: PropTypes.color({ label: '线圆圈填充色-当前站点', defaultValue: '#CB0808', layout: { prefixCls: 'bsth-line' } }), 128 chart_up_line_circle_f_color_current: PropTypes.color({ label: '线圆圈填充色-当前站点', defaultValue: '#CB0808', layout: { prefixCls: 'bsth-line' } }),
120 chart_up_line_circle_f_color_before: PropTypes.color({ label: '线圆圈填充色-前面站点', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }), 129 chart_up_line_circle_f_color_before: PropTypes.color({ label: '线圆圈填充色-前面站点', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }),
121 chart_up_line_circle_f_color_after: PropTypes.color({ label: '线圆圈填充色-后面站点', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }), 130 chart_up_line_circle_f_color_after: PropTypes.color({ label: '线圆圈填充色-后面站点', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }),
122 chart_up_line_circle_r: PropTypes.number({ label: '线圆圈大小', defaultValue: 8, layout: { prefixCls: 'bsth-line' } }), 131 chart_up_line_circle_r: PropTypes.number({ label: '线圆圈大小', defaultValue: 8, layout: { prefixCls: 'bsth-line' } }),
123 - chart_station_text_top_padding: PropTypes.number({ label: '站点文字距离上边', defaultValue: 30, layout: { prefixCls: 'bsth-line' } }), 132 + chart_station_text_top_padding: PropTypes.number({ label: '站点文字距离上边', defaultValue: 60, layout: { prefixCls: 'bsth-line' } }),
124 chart_station_text_font_size_current: PropTypes.number({ label: '站名字体大小-当前站点', defaultValue: 25, layout: { prefixCls: 'bsth-line' } }), 133 chart_station_text_font_size_current: PropTypes.number({ label: '站名字体大小-当前站点', defaultValue: 25, layout: { prefixCls: 'bsth-line' } }),
125 chart_station_text_font_size_before: PropTypes.number({ label: '站名字体大小-前面站点', defaultValue: 20, layout: { prefixCls: 'bsth-line' } }), 134 chart_station_text_font_size_before: PropTypes.number({ label: '站名字体大小-前面站点', defaultValue: 20, layout: { prefixCls: 'bsth-line' } }),
126 chart_station_text_font_size_after: PropTypes.number({ label: '站名字体大小-后面站点', defaultValue: 20, layout: { prefixCls: 'bsth-line' } }), 135 chart_station_text_font_size_after: PropTypes.number({ label: '站名字体大小-后面站点', defaultValue: 20, layout: { prefixCls: 'bsth-line' } }),
127 - chart_station_text_length: PropTypes.number({ label: '站名长度', defaultValue: 100, layout: { prefixCls: 'bsth-line' } }), 136 + chart_station_text_space: PropTypes.number({ label: '站名间距', defaultValue: 10, layout: { prefixCls: 'bsth-line' } }),
  137 + chart_station_text_transform_second: PropTypes.number({ label: '站名滚动间隔(秒)', defaultValue: 6, layout: { prefixCls: 'bsth-line' } }),
128 chart_up_station_text_font_f_color_current: PropTypes.color({ label: '站名颜色-当前站点', defaultValue: '#060D37', layout: { prefixCls: 'bsth-line' } }), 138 chart_up_station_text_font_f_color_current: PropTypes.color({ label: '站名颜色-当前站点', defaultValue: '#060D37', layout: { prefixCls: 'bsth-line' } }),
129 chart_up_station_text_font_f_color_before: PropTypes.color({ label: '站名颜色-前面站点', defaultValue: '#9398B4', layout: { prefixCls: 'bsth-line' } }), 139 chart_up_station_text_font_f_color_before: PropTypes.color({ label: '站名颜色-前面站点', defaultValue: '#9398B4', layout: { prefixCls: 'bsth-line' } }),
130 chart_up_station_text_font_f_color_after: PropTypes.color({ label: '站名颜色-后面站点', defaultValue: '#4556b6', layout: { prefixCls: 'bsth-line' } }), 140 chart_up_station_text_font_f_color_after: PropTypes.color({ label: '站名颜色-后面站点', defaultValue: '#4556b6', layout: { prefixCls: 'bsth-line' } }),
@@ -189,6 +199,9 @@ export default { @@ -189,6 +199,9 @@ export default {
189 <svg class="othergj-eBusStop-line-chart" 199 <svg class="othergj-eBusStop-line-chart"
190 data-code={this.eBusStopData.lineCode} 200 data-code={this.eBusStopData.lineCode}
191 style={svgStyle}> 201 style={svgStyle}>
  202 + <g class="line-wrap">
  203 +
  204 + </g>
192 <g class="arrow-wrap"> 205 <g class="arrow-wrap">
193 <path d={downLinePathD} style={{ 'fill': this.down_line_s_color }}></path> 206 <path d={downLinePathD} style={{ 'fill': this.down_line_s_color }}></path>
194 </g> 207 </g>
@@ -238,6 +251,12 @@ export default { @@ -238,6 +251,12 @@ export default {
238 this.refreshLineSvg() 251 this.refreshLineSvg()
239 // 刷新下部分线svg 252 // 刷新下部分线svg
240 this.refreshDownLineSvg() 253 this.refreshDownLineSvg()
  254 +
  255 + // svg文本滚动监控开启
  256 + if (this.editorMode === 'preview') {
  257 + this.svgTextTransformPositionTimer.count ++
  258 + }
  259 +
241 }, 260 },
242 destroyed () { 261 destroyed () {
243 // 组件删除的时候,删除监控定时器 262 // 组件删除的时候,删除监控定时器
@@ -246,7 +265,12 @@ export default { @@ -246,7 +265,12 @@ export default {
246 clearTimeout(timer) 265 clearTimeout(timer)
247 this.watchWidthHeightTimer.timer = null 266 this.watchWidthHeightTimer.timer = null
248 } 267 }
249 - // TODO:其他timer 268 +
  269 + timer = this.svgTextTransformPositionTimer.timer
  270 + if (timer) {
  271 + clearTimeout(timer)
  272 + this.svgTextTransformPositionTimer.timer = null
  273 + }
250 }, 274 },
251 watch: { 275 watch: {
252 'watchWidthHeightTimer.count' () { // 定时器监控 276 'watchWidthHeightTimer.count' () { // 定时器监控
@@ -272,6 +296,20 @@ export default { @@ -272,6 +296,20 @@ export default {
272 self.watchWidthHeightTimer.count++ 296 self.watchWidthHeightTimer.count++
273 }, self.watchWidthHeightTimer.millisecond) 297 }, self.watchWidthHeightTimer.millisecond)
274 }, 298 },
  299 + 'svgTextTransformPositionTimer.count' () { // 文本位置定时器监控
  300 + let timer = this.svgTextTransformPositionTimer.timer
  301 + if (timer) {
  302 + clearTimeout(timer)
  303 + this.svgTextTransformPositionTimer.timer = null
  304 + }
  305 +
  306 + let self = this
  307 + self.svgTextTransformPositionTimer.timer = setTimeout(function () {
  308 + // console.log('svgTextTransformPositionTimer.count')
  309 + self.transformStationText()
  310 + self.svgTextTransformPositionTimer.count ++
  311 + }, self.svgTextTransformPositionTimer.millisecond)
  312 + },
275 /** 313 /**
276 * 当组件作为子组件使用时(useMode=child),line-chart-outer-div样式的div尺寸无法通过编辑器改变(通用样式) 314 * 当组件作为子组件使用时(useMode=child),line-chart-outer-div样式的div尺寸无法通过编辑器改变(通用样式)
277 * 必须由父组件设定,自组件需要监控改变 315 * 必须由父组件设定,自组件需要监控改变
@@ -336,7 +374,7 @@ export default { @@ -336,7 +374,7 @@ export default {
336 }, 374 },
337 border_size () { 375 border_size () {
338 this.svg_width = this.component_width - this.border_size * 2 376 this.svg_width = this.component_width - this.border_size * 2
339 - this.svg_height = this.component_height - this.text_info_height - this.border_size * 2 377 + this.svg_height = this.component_height - this.border_size * 2
340 378
341 }, 379 },
342 380
@@ -388,21 +426,30 @@ export default { @@ -388,21 +426,30 @@ export default {
388 let svg = this.private_svg 426 let svg = this.private_svg
389 svg.selectAll('g.item text.station_text.up.current') 427 svg.selectAll('g.item text.station_text.up.current')
390 .style('font-size', val) 428 .style('font-size', val)
  429 + this.refreshLineSvg()
391 }, 430 },
392 chart_station_text_font_size_before: function (val) { 431 chart_station_text_font_size_before: function (val) {
393 let svg = this.private_svg 432 let svg = this.private_svg
394 svg.selectAll('g.item text.station_text.up.before') 433 svg.selectAll('g.item text.station_text.up.before')
395 .style('font-size', val) 434 .style('font-size', val)
  435 + this.refreshLineSvg()
396 }, 436 },
397 chart_station_text_font_size_after: function (val) { 437 chart_station_text_font_size_after: function (val) {
398 let svg = this.private_svg 438 let svg = this.private_svg
399 svg.selectAll('g.item text.station_text.up.after') 439 svg.selectAll('g.item text.station_text.up.after')
400 .style('font-size', val) 440 .style('font-size', val)
  441 + this.refreshLineSvg()
401 }, 442 },
402 - chart_station_text_length: function (val) {  
403 - let svg = this.private_svg  
404 - svg.selectAll('g.item text')  
405 - .attr('textLength', val) 443 + chart_station_text_space: function (val) {
  444 + let d3 = this.private_d3
  445 + d3.selectAll('g.item text')
  446 + .attr('textLength', function (d) {
  447 + if (!d.name) {
  448 + return 0
  449 + }
  450 + return parseFloat(d3.select(this).attr('data-text-length-ori')) +
  451 + (d.name.length - 1) * val
  452 + })
406 }, 453 },
407 chart_up_station_text_font_f_color_current: function (val) { 454 chart_up_station_text_font_f_color_current: function (val) {
408 let svg = this.private_svg 455 let svg = this.private_svg
@@ -468,28 +515,35 @@ export default { @@ -468,28 +515,35 @@ export default {
468 // 箭头左下角 515 // 箭头左下角
469 this.down_line_x4 = this.down_line_x3 516 this.down_line_x4 = this.down_line_x3
470 this.down_line_y4 = this.down_line_y2 - self.down_line_s_width 517 this.down_line_y4 = this.down_line_y2 - self.down_line_s_width
471 - // 最左边起点(右下 518 + // 最左边起点(左上
472 this.down_line_x5 = this.down_line_x1 519 this.down_line_x5 = this.down_line_x1
473 this.down_line_y5 = this.down_line_y4 520 this.down_line_y5 = this.down_line_y4
474 }, 521 },
475 refreshLineSvg () { 522 refreshLineSvg () {
476 let self = this 523 let self = this
477 524
478 - // let $jQuery = self.private_jQuery 525 + let $jQuery = self.private_jQuery
479 let d3 = self.private_d3 526 let d3 = self.private_d3
480 527
481 let routeData = self.eBusStopData.routeStationDataList 528 let routeData = self.eBusStopData.routeStationDataList
482 let width = self.svg_width // 内部整个svg的宽度 529 let width = self.svg_width // 内部整个svg的宽度
483 - // let height = self.svg_height // 内部整个svg的高度  
484 - // let svgNameSpace = self.private_svgns 530 + let height = self.svg_height // 内部整个svg的高度
  531 + let svgNameSpace = self.private_svgns
485 let svg = self.private_svg 532 let svg = self.private_svg
486 let chartLeftPadding = self.chart_left_padding 533 let chartLeftPadding = self.chart_left_padding
487 let chartRightPadding = self.chart_right_padding 534 let chartRightPadding = self.chart_right_padding
488 let chartTopPadding = self.chart_top_padding 535 let chartTopPadding = self.chart_top_padding
489 let chartStopNameTopPadding = self.chart_station_text_top_padding 536 let chartStopNameTopPadding = self.chart_station_text_top_padding
490 537
  538 + let textUpMaskRectY = 0;
  539 + let textUpMaskRectHeight = chartStopNameTopPadding;
  540 + let textDownMaskRectY = (height - self.down_line_bottom_padding) -
  541 + (self.down_line_arrow_height + self.down_line_s_width) - 10;
  542 + let textDownMaskRectHeight = self.down_line_bottom_padding +
  543 + self.down_line_arrow_height + self.down_line_s_width + 10;
  544 +
491 // ------------ 1、添加g元素 ---------- // 545 // ------------ 1、添加g元素 ---------- //
492 - let itemsUpdate = svg.selectAll('g.item') 546 + let itemsUpdate = svg.select('g.line-wrap').selectAll('g.item')
493 .data(routeData, function (d) { 547 .data(routeData, function (d) {
494 return d.code 548 return d.code
495 }) 549 })
@@ -504,7 +558,185 @@ export default { @@ -504,7 +558,185 @@ export default {
504 .domain([0, routeData.length - 1]) // 定义域 558 .domain([0, routeData.length - 1]) // 定义域
505 .range([chartLeftPadding, width - chartRightPadding]) // 值域 559 .range([chartLeftPadding, width - chartRightPadding]) // 值域
506 560
507 - // ------------ 2、添加/更新线路图上部分的的path元素 ---------- // 561 + // ------------ 2、添加/更新线路图上部分的站点名称text元素 ---------- //
  562 + itemsEnter.append('text')
  563 + .classed('station_text', true)
  564 + .classed('up', true)
  565 + .classed('current', function (d, i) {
  566 + return self.eBusStopData.currentStopStationIndex === i
  567 + })
  568 + .classed('before', function (d, i) {
  569 + return i < self.eBusStopData.currentStopStationIndex
  570 + })
  571 + .classed('after', function (d, i) {
  572 + return i > self.eBusStopData.currentStopStationIndex
  573 + })
  574 + .style('font-size', function (d, i) {
  575 + if (i === self.eBusStopData.currentStopStationIndex) {
  576 + return self.chart_station_text_font_size_current + 'px'
  577 + } else if (i < self.eBusStopData.currentStopStationIndex) {
  578 + return self.chart_station_text_font_size_before + 'px'
  579 + } else {
  580 + return self.chart_station_text_font_size_after + 'px'
  581 + }
  582 + })
  583 + .style('stroke', function (d, i) {
  584 + if (i === self.eBusStopData.currentStopStationIndex) {
  585 + return self.chart_up_station_text_font_f_color_current
  586 + } else if (i < self.eBusStopData.currentStopStationIndex) {
  587 + return self.chart_up_station_text_font_f_color_before
  588 + } else {
  589 + return self.chart_up_station_text_font_f_color_after
  590 + }
  591 + })
  592 + .text(function (d) {
  593 + if (!d.name) {
  594 + return 0
  595 + }
  596 + return d.name
  597 + })
  598 + .attr('title', function (d) {
  599 + if (!d.name) {
  600 + return 0
  601 + }
  602 + return d.name
  603 + })
  604 + .attr('x', function (d, i) {
  605 + return xScale(i)
  606 + })
  607 + .attr('y', function (d) {
  608 + return chartStopNameTopPadding
  609 + })
  610 + .attr('data-text-length-ori', function (d) { // 原始文本高度
  611 + if (!d.name)
  612 + return 0
  613 + return this.getBBox().height
  614 + })
  615 + .attr('textLength', function (d) {
  616 + if (!d.name) {
  617 + return 0
  618 + }
  619 + return parseFloat(d3.select(this).attr('data-text-length-ori')) +
  620 + (d.name.length - 1) * self.chart_station_text_space
  621 + })
  622 + .attr('data-y-transform-flag', function () {
  623 + // 判定文字上下滚动标识,1:可滚动,0:不可滚动,2:滚动中
  624 + let textMaxLenth = textDownMaskRectY - (textUpMaskRectY + textUpMaskRectHeight)
  625 + let textLength = this.getBBox().height
  626 + if (textLength > textMaxLenth) {
  627 +
  628 + // TODO:使用svg animate测试
  629 + // let textAnimate = document.createElementNS(svgNameSpace, 'animate')
  630 + // d3.select(textAnimate)
  631 + // .attr('attributeName', 'y')
  632 + // .attr('from', 0)
  633 + // .attr('to', chartStopNameTopPadding + 300)
  634 + // .attr('begin', '0s')
  635 + // .attr('dur', '5s')
  636 + // $jQuery(this).append(textAnimate)
  637 +
  638 + return "1"
  639 + } else {
  640 + return "0"
  641 + }
  642 + })
  643 + .attr('data-y-transform-direction', function () {
  644 + // 初始向上滚动,up:向上滚动 down:向下滚动
  645 + return 'up'
  646 + })
  647 + .attr('data-y-transform-distance', function () {
  648 + // y方向初始滚动距离
  649 + let textMaxLength = textDownMaskRectY - (textUpMaskRectY + textUpMaskRectHeight)
  650 + let textLength = this.getBBox().height
  651 + if (textLength > textMaxLength) {
  652 + return textLength - textMaxLength
  653 + } else {
  654 + return 0
  655 + }
  656 + })
  657 +
  658 + itemsUpdate.select('text.station_text')
  659 + .classed('up', true)
  660 + .text(function (d) {
  661 + // 更新的时候需要删除textLength,方便重新计算原始长度
  662 + $jQuery(this).removeAttr('textLength')
  663 + if (!d.name) {
  664 + return 0
  665 + }
  666 + return d.name
  667 + })
  668 + .attr('title', function (d) {
  669 + if (!d.name) {
  670 + return 0
  671 + }
  672 + return d.name
  673 + })
  674 + .attr('x', function (d, i) {
  675 + return xScale(i)
  676 + })
  677 + .attr('y', function (d) {
  678 + return chartStopNameTopPadding
  679 + })
  680 + .attr('data-text-length-ori', function (d) { // 原始文本高度
  681 + if (!d.name)
  682 + return 0
  683 + return this.getBBox().height
  684 + })
  685 + .attr('textLength', function (d) {
  686 + if (!d.name) {
  687 + return 0
  688 + }
  689 + return parseFloat(d3.select(this).attr('data-text-length-ori')) +
  690 + (d.name.length - 1) * self.chart_station_text_space
  691 + })
  692 + .attr('data-y-transform-flag', function () {
  693 + // 判定文字上下是否滚动,1:滚动,0:不滚动
  694 + let textMaxLenth = textDownMaskRectY - (textUpMaskRectY + textUpMaskRectHeight)
  695 + let textLength = this.getBBox().height
  696 + if (textLength > textMaxLenth) {
  697 +
  698 + // // TODO:使用svg animate测试
  699 + // let textAnimate = document.createElementNS(svgNameSpace, 'animate')
  700 + // d3.select(textAnimate)
  701 + // .attr('attributeName', 'y')
  702 + // .attr('from', 0)
  703 + // .attr('to', chartStopNameTopPadding + 300)
  704 + // .attr('begin', '0s')
  705 + // .attr('dur', '5s')
  706 + // $jQuery(this).append(textAnimate)
  707 +
  708 + return "1"
  709 + } else {
  710 + return "0"
  711 + }
  712 + })
  713 + .attr('data-y-transform-distance', function () {
  714 + // y方向初始滚动距离,初始向上滚动
  715 + let textMaxLength = textDownMaskRectY - (textUpMaskRectY + textUpMaskRectHeight)
  716 + let textLength = this.getBBox().height
  717 + if (textLength > textMaxLength) {
  718 + // console.log(textMaxLength - textLength)
  719 + return textMaxLength - textLength
  720 + } else {
  721 + return 0
  722 + }
  723 + })
  724 + .attr('data-y-transform-direction', function () {
  725 + // 初始向上滚动,up:向上滚动 down:向下滚动
  726 + return 'up'
  727 + })
  728 + .attr('data-y-transform-distance', function () {
  729 + // y方向初始滚动距离
  730 + let textMaxLength = textDownMaskRectY - (textUpMaskRectY + textUpMaskRectHeight)
  731 + let textLength = this.getBBox().height
  732 + if (textLength > textMaxLength) {
  733 + return textLength - textMaxLength
  734 + } else {
  735 + return 0
  736 + }
  737 + })
  738 +
  739 + // ------------ 3、添加/更新线路图上部分的的path元素 ---------- //
508 let upLineFun = d3.line() 740 let upLineFun = d3.line()
509 .x(xScale) 741 .x(xScale)
510 .y(function () { 742 .y(function () {
@@ -522,7 +754,35 @@ export default { @@ -522,7 +754,35 @@ export default {
522 return i < routeData.length - 1 ? upLineFun([i, i + 1]) : '' 754 return i < routeData.length - 1 ? upLineFun([i, i + 1]) : ''
523 }) 755 })
524 756
525 - // ------------ 3、添加/更新线路图上部分的circle元素 ---------- // 757 + // ------------ 4-up_mask、添加/更新上部分rect ------------- //
  758 + // 当text向上移动的时候,遮住超出的部分,类似div的overflow
  759 + itemsEnter.append('rect')
  760 + .classed('up_mask', true)
  761 + .style('fill', self.svg_background)
  762 + .style('stroke-width', 0)
  763 + .attr('x', function (d, i) {
  764 + let text_bound = d3.select(this.parentNode).select('text').node().getBBox();
  765 + return text_bound.x
  766 + })
  767 + .attr('y', textUpMaskRectY)
  768 + .attr('width', function () {
  769 + let text_bound = d3.select(this.parentNode).select('text').node().getBBox();
  770 + return text_bound.width
  771 + })
  772 + .attr('height', textUpMaskRectHeight)
  773 + itemsUpdate.select('rect.up_mask')
  774 + .attr('x', function (d, i) {
  775 + let text_bound = d3.select(this.parentNode).select('text').node().getBBox();
  776 + return text_bound.x
  777 + })
  778 + .attr('y', textUpMaskRectY)
  779 + .attr('width', function () {
  780 + let text_bound = d3.select(this.parentNode).select('text').node().getBBox();
  781 + return text_bound.width
  782 + })
  783 + .attr('height', textUpMaskRectHeight)
  784 +
  785 + // ------------ 4、添加/更新线路图上部分的circle元素 ---------- //
526 itemsEnter.select(function (d) { 786 itemsEnter.select(function (d) {
527 return d.type !== 1 ? this : null 787 return d.type !== 1 ? this : null
528 }).append('circle') 788 }).append('circle')
@@ -564,70 +824,82 @@ export default { @@ -564,70 +824,82 @@ export default {
564 return chartTopPadding 824 return chartTopPadding
565 }) 825 })
566 826
567 - // ------------ 4、添加/更新线路图上部分的站点名称text元素 ---------- //  
568 - itemsEnter.append('text')  
569 - .classed('station_text', true)  
570 - .classed('up', true)  
571 - .classed('current', function (d, i) {  
572 - return self.eBusStopData.currentStopStationIndex === i 827 + // ------------ 4-down_mask、添加/更新上部分rect ------------- //
  828 + // 当text向下移动的时候,遮住超出的部分,类似div的overflow
  829 + itemsEnter.append('rect')
  830 + .classed('down_mask', true)
  831 + .style('fill', self.svg_background)
  832 + .style('stroke-width', 0)
  833 + .attr('x', function () {
  834 + let text_bound = d3.select(this.parentNode).select('text').node().getBBox();
  835 + return text_bound.x
573 }) 836 })
574 - .classed('before', function (d, i) {  
575 - return i < self.eBusStopData.currentStopStationIndex 837 + .attr('y', function () {
  838 + return textDownMaskRectY
576 }) 839 })
577 - .classed('after', function (d, i) {  
578 - return i > self.eBusStopData.currentStopStationIndex 840 + .attr('width', function () {
  841 + let text_bound = d3.select(this.parentNode).select('text').node().getBBox();
  842 + return text_bound.width
579 }) 843 })
580 - .style('font-size', function (d, i) {  
581 - if (i === self.eBusStopData.currentStopStationIndex) {  
582 - return self.chart_station_text_font_size_current + 'px'  
583 - } else if (i < self.eBusStopData.currentStopStationIndex) {  
584 - return self.chart_station_text_font_size_before + 'px'  
585 - } else {  
586 - return self.chart_station_text_font_size_after + 'px'  
587 - } 844 + .attr('height', function () {
  845 + return textDownMaskRectHeight
588 }) 846 })
589 - .style('stroke', function (d, i) {  
590 - if (i === self.eBusStopData.currentStopStationIndex) {  
591 - return self.chart_up_station_text_font_f_color_current  
592 - } else if (i < self.eBusStopData.currentStopStationIndex) {  
593 - return self.chart_up_station_text_font_f_color_before  
594 - } else {  
595 - return self.chart_up_station_text_font_f_color_after  
596 - } 847 + itemsUpdate.select('rect.down_mask')
  848 + .attr('x', function () {
  849 + let text_bound = d3.select(this.parentNode).select('text').node().getBBox();
  850 + return text_bound.x
597 }) 851 })
598 - .attr('textLength', self.chart_station_text_length)  
599 - .text(function (d) {  
600 - if (!d.name) {  
601 - return 0  
602 - }  
603 - return d.name 852 + .attr('y', function () {
  853 + return textDownMaskRectY
604 }) 854 })
605 - .attr('title', function (d) {  
606 - return d.name 855 + .attr('width', function () {
  856 + let text_bound = d3.select(this.parentNode).select('text').node().getBBox();
  857 + return text_bound.width
607 }) 858 })
608 - .attr('x', function (d, i) {  
609 - return xScale(i) 859 + .attr('height', function () {
  860 + return textDownMaskRectHeight
610 }) 861 })
611 - .attr('y', function (d) {  
612 - return chartStopNameTopPadding 862 +
  863 + },
  864 + transformStationText () {
  865 + let self = this
  866 + let d3 = self.private_d3
  867 + d3.selectAll('text.station_text')
  868 + .select(function () {
  869 + let transform_flag = d3.select(this).attr('data-y-transform-flag')
  870 + return transform_flag === "1" ? this : null
613 }) 871 })
614 - itemsUpdate.select('text.station_text')  
615 - .classed('up', true)  
616 - .text(function (d) {  
617 - if (!d.name) {  
618 - return 0 872 + .transition()
  873 + .duration(self.chart_station_text_transform_second * 1000)
  874 + .ease(d3.easeCubic)
  875 + .attr('data-y-transform-flag', '2') // 状态变成滚动中
  876 + .attr('y', function () {
  877 + // console.log('go y transform')
  878 +
  879 + // 滚动的y坐标
  880 + let y = this.getBBox().y
  881 + // 滚动的方向
  882 + let dir = d3.select(this).attr('data-y-transform-direction')
  883 + // 滚动的距离
  884 + let y_transform_distance = parseInt(d3.select(this).attr('data-y-transform-distance'))
  885 + if (dir === 'up') {
  886 + return y - y_transform_distance
  887 + } else {
  888 + return y + y_transform_distance
619 } 889 }
620 - return d.name  
621 - })  
622 - .attr('title', function (d) {  
623 - return d.name  
624 - })  
625 - .attr('x', function (d, i) {  
626 - return xScale(i)  
627 }) 890 })
628 - .attr('y', function (d) {  
629 - return chartStopNameTopPadding 891 + .on('end', function () {
  892 + // 重置滚动状态
  893 + d3.select(this).attr('data-y-transform-flag', 1)
  894 + // 切换滚动方向
  895 + let dir = d3.select(this).attr('data-y-transform-direction')
  896 + if (dir === 'up') {
  897 + d3.select(this).attr('data-y-transform-direction', 'down')
  898 + } else {
  899 + d3.select(this).attr('data-y-transform-direction', 'up')
  900 + }
630 }) 901 })
631 } 902 }
  903 +
632 } 904 }
633 } 905 }
front-end/h5/src/components/core/plugins/bsth/othergj/linechart/list/css/othergj-eBusStop-line-chart-list.css 0 → 100644
  1 +/*
  2 + 内部使用的是border-box
  3 + 注意:
  4 + 1、这个设置很重要,因为内部计算width是减去两侧border的
  5 + 2、在编辑器模式下,外层的.ant-layout会给内层所有元素设置border-box,此时你不设置无所谓
  6 + 3、但是在打包预览模式下,是没有外层.ant-layout定义的,此时如果组件内部不定义,则会使用content-box,会和内部计算宽度产生偏差
  7 +*/
  8 +.othergj-eBusStop-line-chart-list-outer-div, .othergj-eBusStop-line-chart-list-outer-div * {
  9 + box-sizing: border-box;
  10 +}
  11 +
  12 +/**
  13 + 这里使用float布局,当多个线路模拟图排列的时候
  14 + 1、如果最外层div使用position: relative或不指定position,
  15 + 最外层的div位置会有偏差,滚动列表是会造成距离偏差
  16 + 2、如果使用position:absolute,需要指定top,可以算出的,但是麻烦
  17 + 3、直接使用float:left,不会有问题,因为宽度是死的,高度是活的,排列时没有偏差
  18 + */
  19 +.othergj-eBusStop-line-chart-list-outer-div .othergj-eBusStop-line-chart-outer-div {
  20 + float: left;
  21 +}
front-end/h5/src/components/core/plugins/bsth/othergj/linechart/list/models/othergj-eBusStop-line-chart-list-scrollPage-innerData.js 0 → 100644
  1 +/**
  2 + * othergj-eBusStop-line-chart-scrollPage.js 内部使用数据对象
  3 + */
  4 +
  5 +import Utils from 'core/plugins/bsth/bsth-utils'
  6 +import { StationData, RouteData, EBusStopData } from 'core/plugins/bsth/othergj/linechart/chart/models/eBusStopData'
  7 +
  8 +class ScrollPageInnerDataItem {
  9 + /**
  10 + * 构造函数。
  11 + * @param width int 对应eBusStop-line-chart组件宽度
  12 + * @param height int 对应eBusStop-line-chart组件高度
  13 + * @param cssTop int 对应eBusStop-line-chart组件距离顶部css top值
  14 + * @param itemIndex int 每页中的item下标(从0开始)
  15 + * @param pageIndex int 第几页下标(从0开始)
  16 + * @param eBusStopData EBusStopData 对应eBusStop-line-chart组件使用的数据对象
  17 + */
  18 + constructor (width = 0, height = 0, cssTop, itemIndex, pageIndex, eBusStopData) {
  19 + // 数据对象
  20 + this._eBusStopData = eBusStopData
  21 +
  22 + // ------------- 滚动列表用的数据 ------------ //
  23 + this._width = width
  24 + this._height = height
  25 + this._cssTop = cssTop
  26 + this._itemIndex = itemIndex
  27 + this._pageIndex = pageIndex
  28 + }
  29 +
  30 + get width () {
  31 + return this._width
  32 + }
  33 + get height () {
  34 + return this._height
  35 + }
  36 +
  37 + get top () {
  38 + return this._cssTop
  39 + }
  40 +
  41 + /**
  42 + * 使用类本身对象创建。
  43 + * @param dataItem ScrollPageInnerDataItem
  44 + * @return ScrollPageInnerDataItem
  45 + */
  46 + static createByDataItem (dataItem) {
  47 + return new ScrollPageInnerDataItem(
  48 + 0, 0,
  49 + dataItem._cssTop,
  50 + dataItem._itemIndex,
  51 + dataItem._pageIndex,
  52 + dataItem._eBusStopData
  53 + )
  54 + }
  55 +
  56 + // TODO:
  57 +}
  58 +
  59 +class ScrollPageInnerData {
  60 + /**
  61 + * 构造函数。
  62 + * @param pageSize 每页大小
  63 + * @param width 列表宽度
  64 + * @param height 列表高度
  65 + */
  66 + constructor (pageSize, width, height) {
  67 + this._pageSize = pageSize
  68 + this._width = width
  69 + this._height = height
  70 +
  71 + // --------------- 内部数据对象 ---------------- //
  72 + // ScrollPageInnerDataItem 类型数组
  73 + this._innerDataItemList = []
  74 + this._pageCount = 0 // 一共多少页
  75 +
  76 + // --------------- 内部滚动数据对象 --------------- //
  77 + // 滚动用的 ScrollPageInnerDataItem 类型数组(根据不同的滚动策略会和_innerDataItemList不一致)
  78 + this._scrollDataItemList = []
  79 + this._currentScrollIndex = 0 // 当前滚动项index
  80 + this._nextScrollIndex = 1 // 下一个滚动项index
  81 + this._scrollAnimateTimer = { // 滚动动画效果timer
  82 + timer: undefined,
  83 + count: 0,
  84 + millisecond: 1
  85 + }
  86 + }
  87 +
  88 + // ---------------- get/set方法 -------------- //
  89 + set pageSize (val) { // 设置每页大小
  90 + this._pageSize = val
  91 + this._pageCount = Math.ceil(this._innerDataItemList.length / this._pageSize)
  92 + // 重新计算_scrollDataItemList
  93 + _private_refreshScrollData.call(this)
  94 + }
  95 +
  96 + get scrollDataItemList () { // 返回滚动数据集
  97 + return this._scrollDataItemList
  98 + }
  99 +
  100 + set width (val) {
  101 + this._width = val
  102 + // 刷新滚动数据中 宽,高,top
  103 + _private_refreshScrollDataSizeProperty.call(this)
  104 + }
  105 +
  106 + set height (val) {
  107 + this._height = val
  108 + // 刷新滚动数据中 宽,高,top
  109 + _private_refreshScrollDataSizeProperty.call(this)
  110 + }
  111 +
  112 + // --------------------- 分页移动方法 --------------------- //
  113 + /**
  114 + * eBusStop-line-chart-list-scrollPage组件联动,向上滚动翻页
  115 + * 主要分页逻辑:每次向上移动一个chart,第一个chart接到最后一个chart组成一个环滚动翻
  116 + * @param scrollListComponent eBusStop-line-chart-list-scrollPage组件
  117 + */
  118 + scrollUp (scrollListComponent) {
  119 + if (this._scrollDataItemList.length <= this._pageSize) { // 总数据小于页大小,不滚动
  120 + return
  121 + }
  122 +
  123 + if (this._scrollAnimateTimer.timer) {
  124 + try {
  125 + clearInterval(this._scrollAnimateTimer.timer)
  126 + } catch (err) {
  127 + }
  128 + this._scrollAnimateTimer.timer = undefined
  129 + }
  130 +
  131 + // 往上滚动,相当于视口view向下移动
  132 + let viewTopFrom = this._scrollDataItemList[this._currentScrollIndex].top
  133 + let viewTopTo = this._scrollDataItemList[this._nextScrollIndex].top
  134 + let speed = scrollListComponent.scroll_speed // 每秒移动像素数
  135 + let step = speed / 1000 // 每毫秒移动像素数
  136 + // let step = (topTo - topFrom) / 20 // 每毫秒移动距离差的5分之一
  137 + let self = this
  138 + self._scrollAnimateTimer.timer = setInterval(function () {
  139 + self._scrollAnimateTimer.count++
  140 + let currentViewTop = viewTopFrom + self._scrollAnimateTimer.count * step
  141 + // console.log(currentViewTop)
  142 + if (currentViewTop > viewTopTo || (viewTopTo - currentViewTop) < step) {
  143 + scrollListComponent.$emit('scrollTop', viewTopTo)
  144 + self._scrollAnimateTimer.count = 0
  145 +
  146 + // console.log(self._pageCount)
  147 + // console.log(self._scrollDataItemList[self._nextScrollIndex].pageIndex)
  148 + if (self._scrollDataItemList[self._nextScrollIndex].pageIndex === self._pageCount) {
  149 + scrollListComponent.$emit('scrollTop', self._scrollDataItemList[0].top)
  150 + self._currentScrollIndex = 0
  151 + self._nextScrollIndex = 1
  152 + } else {
  153 + self._currentScrollIndex = self._nextScrollIndex
  154 + self._nextScrollIndex++
  155 + }
  156 +
  157 + if (self._scrollAnimateTimer.timer) {
  158 + try {
  159 + clearInterval(self._scrollAnimateTimer.timer)
  160 + } catch (err) {
  161 + }
  162 + self._scrollAnimateTimer.timer = null
  163 + }
  164 +
  165 + scrollListComponent.scrollTimer.count++
  166 + } else {
  167 + scrollListComponent.$emit('scrollTop', currentViewTop)
  168 + }
  169 +
  170 + }, 1)
  171 + }
  172 +
  173 + // ----------------------- 数据方法 --------------------- //
  174 + /**
  175 + * 重置内部数据
  176 + */
  177 + resetData () {
  178 + // ------------ 重置内部数据对象 ------------ //
  179 + this._innerDataItemList.splice(0, this._innerDataItemList.length) // 直接删除数据内部数据,而不是 = []
  180 + this._pageCount = 0
  181 +
  182 + // ------------ 重置内部滚动数据对象 ---------- //
  183 + this._scrollDataItemList.splice(0, this._scrollDataItemList.length)
  184 + this._currentScrollIndex = 0
  185 + this._nextScrollIndex = 1
  186 + if (this._scrollAnimateTimer.timer) {
  187 + try {
  188 + clearInterval(this._scrollAnimateTimer.timer)
  189 + } catch (err) {
  190 + }
  191 + }
  192 + this._scrollAnimateTimer.timer = undefined
  193 + this._scrollAnimateTimer.count = 0
  194 + }
  195 +
  196 + /**
  197 + * 使用远程数据刷新内部数据。
  198 + * @param remoteDataList Object
  199 + */
  200 + refreshDataWithRemoteData (remoteDataList) {
  201 + // 远程数据格式参考 http://36.134.151.106:19102/General_Interface/getArriveVO?deviceId=66MH0001
  202 + if (!remoteDataList || !remoteDataList.length) {
  203 + return
  204 + }
  205 +
  206 + // 1、按照线路名字_线路编码分组数据
  207 + let dataGroupByLineNameCode = Utils.listGroupBy(remoteDataList, function (d) {
  208 + return d.lineName + '_' + d.lineCode
  209 + })
  210 + // 2、处理数据,循环计算每条线路的数据 TODO:
  211 + for (let internalData of this._innerDataItemList) {
  212 + let key = internalData._eBusStopData.lineName + '_' + internalData._eBusStopData.lineCode
  213 + if (dataGroupByLineNameCode[key]) {
  214 + // let info = dataGroupByLineNameCode[key][0]
  215 + // // 更新系统时间
  216 + // let systemDateTime = (info['currDate'] || '') + ' ' + (info['currTime'])
  217 + // internalData._eBusStopData._systemDateTime = systemDateTime
  218 + // // 更新到达时间数组
  219 + // let arriveTimes = []
  220 + // if (info['arrive'] && info['arrive'].length) {
  221 + // info['arrive'].map(arrive => {
  222 + // arriveTimes.push(arrive.timeFormat || '')
  223 + // })
  224 + // }
  225 + // // 设置arriveTimes
  226 + // console.log(arriveTimes)
  227 + // internalData._eBusStopData.arriveTimes = arriveTimes
  228 +
  229 + // TODO:
  230 + }
  231 + }
  232 +
  233 + // TODO:gps数据
  234 +
  235 + }
  236 +
  237 + // --------------------------- static构建方法 ------------------------- //
  238 + /**
  239 + * 使用远程数据生成对象。
  240 + * @param pageSize 每页大小
  241 + * @param width 列表宽度
  242 + * @param height 列表高度
  243 + * @param remoteDataList Object
  244 + * @return ScrollPageInnerData
  245 + */
  246 + static generateDataListByRemoteData (pageSize, width, height, remoteDataList) {
  247 + let rtnData = new ScrollPageInnerData(
  248 + pageSize, width, height
  249 + )
  250 +
  251 + // 1、重置内部数据
  252 + rtnData.resetData()
  253 + // 1-1、如果远端数据为空,直接返回
  254 + if (!remoteDataList || !remoteDataList.length) {
  255 + return rtnData
  256 + }
  257 +
  258 + // 2、计算内部数据对象
  259 + rtnData._innerDataItemList.splice(0, rtnData._innerDataItemList.length)
  260 +
  261 + // 2-1、使用远端数据构造内部数据
  262 + // 远程数据格式参考 http://36.134.151.106:19102/General_Interface/getArriveVO?deviceId=66MH0001
  263 + remoteDataList.map(info => {
  264 + let lineName = info['lineName'] || '' // 线路名称
  265 + let lineCode = info['lineCode'] || '' // 线路代码
  266 + let lineDir = info['direction'] || '' // 线路方向
  267 + let startTime = '' // 首班车时间
  268 + let endTime = '' // 末班车时间
  269 + if (lineDir === '0') {
  270 + startTime = info['startEarlyTime'] || ''
  271 + endTime = info['startLateTime'] || ''
  272 + } else if (lineDir === '1') {
  273 + startTime = info['endEarlyTime'] || ''
  274 + endTime = info['endLateTime'] || ''
  275 + } else {
  276 + startTime = ''
  277 + endTime = ''
  278 + }
  279 + let currentStopIndexList = [] // 当前站点索引列表(可能有多个)
  280 + let stationDataList = [] // 站点路由列表
  281 + if (info['lineRoute'] && info['lineRoute'].length) {
  282 + info['lineRoute'].map((station, i) => {
  283 + if (station['this'] && station['this'] === 'yes') {
  284 + currentStopIndexList.push(i)
  285 + }
  286 + let stationData = new StationData(
  287 + station['stationName'] || '',
  288 + station['stationCode'] || '',
  289 + )
  290 + stationDataList.push(stationData)
  291 + })
  292 + }
  293 +
  294 + let currentStopIndex = 0 // 当前站点索引(默认取第一个)
  295 + if (currentStopIndexList.length > 0) {
  296 + currentStopIndex = currentStopIndexList[0]
  297 + }
  298 + let routeData = new RouteData(currentStopIndex, stationDataList)
  299 + rtnData._innerDataItemList.push(
  300 + new ScrollPageInnerDataItem(0, 0, 0, 0, 0,
  301 + new EBusStopData(lineName, lineCode, routeData, startTime, endTime)))
  302 +
  303 + // TODO:gps数据
  304 + })
  305 +
  306 + // 2.2、如果不足一页,补足一页数据,用空数据补充(TODO:如果要测试分页,可以在这里添加更多的emptyTestData)
  307 + let _size = pageSize - rtnData._innerDataItemList.length
  308 + if (_size > 0) {
  309 + for (let i = 0; i < _size; i++) {
  310 + rtnData._innerDataItemList.push(new ScrollPageInnerDataItem(
  311 + 0, 0, 0, 0, 0, EBusStopData.generateTestData_null()))
  312 + }
  313 + }
  314 +
  315 + // 2.3、一共有多少页
  316 + rtnData._pageCount = Math.ceil(rtnData._innerDataItemList.length / rtnData._pageSize)
  317 +
  318 + // 3、计算内部滚动数据对象
  319 + _private_refreshScrollData.call(rtnData)
  320 +
  321 + return rtnData
  322 + }
  323 +
  324 + /**
  325 + * static方法,使用测试数据生成对象。
  326 + * @param pageSize 每页大小
  327 + * @param width 列表宽度
  328 + * @param height 列表高度
  329 + * @return ScrollPageInnerData
  330 + */
  331 + static generateDataListByTest (pageSize, width, height) {
  332 + let rtnData = new ScrollPageInnerData(
  333 + pageSize, width, height
  334 + )
  335 +
  336 + // 1、重置内部数据
  337 + rtnData.resetData()
  338 +
  339 + // 2、计算内部数据对象
  340 + rtnData._innerDataItemList.splice(0, rtnData._innerDataItemList.length)
  341 + // 2-1、测试数据
  342 + let eBusStopData1 = EBusStopData.generateTestData()
  343 + let eBusStopData2 = EBusStopData.generateTestData()
  344 + eBusStopData2._lineName = "线路2"
  345 + eBusStopData2._lineCode = "2"
  346 + let eBusStopDataList = [eBusStopData1, eBusStopData2]
  347 + eBusStopDataList.map(stopData => {
  348 + rtnData._innerDataItemList.push(new ScrollPageInnerDataItem(
  349 + 0, 0, 0, 0, 0, stopData
  350 + ))
  351 + })
  352 +
  353 + // TODO:gps数据
  354 +
  355 +
  356 + // 2.2、如果不足一页,补足一页数据,用空数据补充(TODO:如果要测试分页,可以在这里添加更多的emptyTestData)
  357 + let _size = pageSize - rtnData._innerDataItemList.length
  358 + if (_size > 0) {
  359 + for (let i = 0; i < _size; i++) {
  360 + rtnData._innerDataItemList.push(new ScrollPageInnerDataItem(
  361 + 0, 0, 0, 0, 0, EBusStopData.generateTestData_null()))
  362 + }
  363 + }
  364 +
  365 + // 2.3、一共有多少页
  366 + rtnData._pageCount = Math.ceil(rtnData._innerDataItemList.length / rtnData._pageSize)
  367 +
  368 + // 3、计算内部滚动数据对象
  369 + _private_refreshScrollData.call(rtnData)
  370 +
  371 + return rtnData
  372 + }
  373 +}
  374 +
  375 +// ---------------- private私有方法 -----------------//
  376 +/**
  377 + * 计算内部滚动数据。
  378 + */
  379 +function _private_refreshScrollData () {
  380 + this._scrollDataItemList.splice(0, this._scrollDataItemList.length)
  381 +
  382 + // 3.1、拷贝属性赋值
  383 + for (let dataItem of this._innerDataItemList) {
  384 + // 注意这里直接拷贝_innerDataItemList元素属性,然后new新的ScrollListInnerDataItem对象
  385 + this._scrollDataItemList.push(
  386 + ScrollPageInnerDataItem.createByDataItem(dataItem)
  387 + )
  388 + }
  389 + // 3.2、如果总数据小于页大小,不用计算其他滚动数据,返回
  390 + if (this._innerDataItemList.length <= this._pageSize) {
  391 + return
  392 + }
  393 + // 3.3、计算每条数据的 itemIndex pageIndex 属性
  394 + for (let i = 0; i < this._pageCount; i++) { // 计算itemIndex pageIndex
  395 + for (let j = 0; j < this._pageSize; j++) {
  396 + let index = i * this._pageSize + j
  397 + if (index === this._scrollDataItemList.length) { // 超出记录退出
  398 + break
  399 + }
  400 + let innerDataItem = this._scrollDataItemList[i * this._pageSize + j]
  401 + innerDataItem.itemIndex = j
  402 + innerDataItem.pageIndex = i
  403 + }
  404 + }
  405 + // 3.4、在最后添加第一页的数据(为了无缝滚动需要),同时pageIndex要加1
  406 + // 注意:添加的一页不计算进this.pageCount中
  407 + for (let i = 0; i < this._pageSize; i++) {
  408 + let InnerDataItem = ScrollPageInnerDataItem.createByDataItem(this._innerDataItemList[i])
  409 + InnerDataItem.pageIndex = this._pageCount
  410 + this._scrollDataItemList.push(InnerDataItem)
  411 + }
  412 + // 3.5、计算每个元素的宽,高,top
  413 + _private_refreshScrollDataSizeProperty.call(this)
  414 +}
  415 +
  416 +/**
  417 + * 刷新滚动数据中 宽,高,top
  418 + */
  419 +function _private_refreshScrollDataSizeProperty () {
  420 + // TODO:先直接除假设每个item高度相同,后面再改
  421 + let scrollHeight = Math.floor(this._height / this._pageSize)
  422 + for (let i = 0; i < this._scrollDataItemList.length; i++) {
  423 + let innerDataItem = this._scrollDataItemList[i]
  424 + innerDataItem._width = this._width
  425 + innerDataItem._height = scrollHeight
  426 + innerDataItem._cssTop = i * scrollHeight
  427 + }
  428 +}
  429 +
  430 +export {
  431 + ScrollPageInnerData,
  432 + ScrollPageInnerDataItem
  433 +}
front-end/h5/src/components/core/plugins/bsth/othergj/linechart/list/othergj-eBusStop-line-chart-list-scrollPage.js 0 → 100644
  1 +/**
  2 + * 自定义线路模拟图组件列表滚动Page
  3 + * 注意:此组件不单独使用,只用在 othergj-eBusStop-line-chart-list 组件内部)
  4 + */
  5 +
  6 +import { jsonp } from 'vue-jsonp'
  7 +import { ScrollPageInnerData } from 'core/plugins/bsth/othergj/linechart/list/models/othergj-eBusStop-line-chart-list-scrollPage-innerData'
  8 +
  9 +export default {
  10 + props: {
  11 + // ---------------- 父组件传递的属性 ---------------- //
  12 + // 编辑模式
  13 + editorMode: { type: String, required: true },
  14 + // 每页大小
  15 + page_size: { type: Number, required: true },
  16 + // 列表宽度
  17 + list_width: { type: Number, required: true },
  18 + // 列表高度
  19 + list_height: { type: Number, required: true },
  20 + // 滚动时间间隔(秒)
  21 + scroll_seconds: { type: Number, required: true },
  22 + // 滚动速度(像素/秒)
  23 + scroll_speed: { type: Number, required: true },
  24 +
  25 + // 获取远端数据url
  26 + remote_data_url: { type: String, required: true },
  27 + // 获取远端数据url参数:站牌设备id
  28 + remote_data_url_param_device_id: { type: String, required: true },
  29 + // 获取远端数据间隔(秒)
  30 + remote_data_refresh_seconds: { type: Number, required: true }
  31 + },
  32 + computed: {
  33 + remoteUrl () {
  34 + return this.remote_data_url + '?deviceId=' + this.remote_data_url_param_device_id
  35 + }
  36 + },
  37 +
  38 + data () {
  39 + return {
  40 + // --------------- lazy加载slot --------------- //
  41 + lazySlot: true,
  42 +
  43 + // --------------- 滚动翻页数据对象 --------------//
  44 + scrollPageInnerData: null,
  45 + initLoading: true,
  46 + initLoadingText: '',
  47 +
  48 + // ---------------- 内部的定时timer --------------- //
  49 + scrollTimer: { // 滚动间隔timer
  50 + timer: undefined,
  51 + count: 0
  52 + },
  53 + remoteDataTimer: { // 远程数据刷新间隔timer
  54 + timer: undefined,
  55 + count: 0
  56 + }
  57 + }
  58 + },
  59 + mounted () {
  60 + // 1、初始化数据
  61 + // 1.1、edit模式下,使用测试数据
  62 + if (this.editorMode === 'edit') {
  63 + this.initLoading = true
  64 + this.initLoadingText = '初始化数据...'
  65 + this.scrollPageInnerData = ScrollPageInnerData.generateDataListByTest(
  66 + this.page_size, this.list_width, this.list_height)
  67 + // 发送bindData事件,父组件绑定该事件
  68 + this.$emit('bindData', this.scrollPageInnerData.scrollDataItemList)
  69 + this.initLoading = false
  70 + this.lazySlot = false
  71 +
  72 + }
  73 + // 1.2、preview模式下,使用远程数据
  74 + if (this.editorMode === 'preview') {
  75 + this.initDataByRemoteApi()
  76 + }
  77 + },
  78 + destroyed () {
  79 + // 重置滚动间隔timer
  80 + let scrollTimer = this.scrollTimer.timer
  81 + if (scrollTimer) {
  82 + try {
  83 + clearTimeout(scrollTimer)
  84 + } catch (err) {}
  85 + }
  86 + this.scrollTimer.timer = undefined
  87 +
  88 + // 重置远程数据刷新间隔timer
  89 + let remoteDataTimer = this.remoteDataTimer.timer
  90 + if (remoteDataTimer) {
  91 + try {
  92 + clearTimeout(remoteDataTimer)
  93 + } catch (err) {}
  94 + }
  95 + this.remoteDataTimer.timer = undefined
  96 +
  97 + // 重置滚动翻页数据对象
  98 + if (this.scrollPageInnerData) {
  99 + this.scrollPageInnerData.resetData()
  100 + }
  101 + },
  102 + watch: {
  103 + 'scrollTimer.count' () {
  104 + let timer = this.scrollTimer.timer
  105 + if (timer) {
  106 + try {
  107 + clearTimeout(timer)
  108 + } catch (err) {}
  109 + this.scrollTimer.timer = undefined
  110 + }
  111 + let self = this
  112 + this.scrollTimer.timer = setTimeout(function () {
  113 + self.startScroll()
  114 + // self.scrollTimer.count++ // 滚动完成再触发,this.scrollListInnerData.scrollUp触发
  115 + }, this.scroll_seconds * 1000)
  116 + },
  117 + 'remoteDataTimer.count' () {
  118 + let timer = this.remoteDataTimer.timer
  119 + if (timer) {
  120 + try {
  121 + clearTimeout(timer)
  122 + } catch (err) {}
  123 + }
  124 + let self = this
  125 + this.remoteDataTimer.timer = setTimeout(function () {
  126 + self.refreshDataByRemoteApi()
  127 + }, this.remote_data_refresh_seconds * 1000)
  128 + },
  129 + // -------------------- 监控父组件传递的属性 --------------- //
  130 + page_size (val) {
  131 + // 只在edit模式下监控,preview模式下不监控
  132 + if (this.editorMode === 'edit') { // 使用测试数据
  133 + this.scrollPageInnerData.pageSize = val
  134 + }
  135 + },
  136 + list_width (val) {
  137 + if (this.editorMode === 'edit') {
  138 + this.scrollPageInnerData.width = val
  139 + } else {
  140 + // TODO:
  141 + }
  142 + },
  143 + list_height (val) {
  144 + if (this.editorMode === 'edit') {
  145 + this.scrollPageInnerData.height = val
  146 + } else {
  147 + // TODO:
  148 + }
  149 + }
  150 + },
  151 + render () {
  152 + // TODO:暂时是没有内容显示的,只处理内部数据,后面再根据不同的错误显示内容
  153 + return (
  154 + <a-spin tip={this.initLoadingText} spinning={this.initLoading} size="large">
  155 + {
  156 + !this.lazySlot ? this.$slots.default : ''
  157 + }
  158 + </a-spin>
  159 + )
  160 + },
  161 + methods: {
  162 + startScroll () {
  163 + this.scrollPageInnerData.scrollUp(this)
  164 + },
  165 + initDataByRemoteApi () { // 使用后台api初始化数据
  166 + this.initLoading = true
  167 + this.initLoadingText = '初始化数据...'
  168 + jsonp(this.remoteUrl).then(remoteDataList => {
  169 + if (!remoteDataList || !remoteDataList.length) {
  170 + this.initLoadingText = `远端数据为空,等待${this.remote_data_refresh_seconds}秒后重新获取,请稍后...`
  171 + this.remoteDataTimer.count++
  172 + } else {
  173 + this.scrollPageInnerData = ScrollPageInnerData.generateDataListByRemoteData(
  174 + this.page_size, this.list_width, this.list_height, remoteDataList)
  175 + // this.scrollPageInnerData = ScrollPageInnerData.generateDataListByTest(
  176 + // this.page_size, this.list_width, this.list_height)
  177 +
  178 + // 发送bindData事件,父组件绑定该事件
  179 + this.$emit('bindData', this.scrollPageInnerData.scrollDataItemList)
  180 + this.initLoading = false
  181 + this.lazySlot = false
  182 + // 启动滚动分页,后台数据刷新
  183 + this.scrollTimer.count++
  184 + this.remoteDataTimer.count++
  185 + }
  186 + }).catch(err => {
  187 + console.log(err)
  188 + this.$message.error(`获取远端数据失败,状态:${err.status},错误:${err.statusText}`, 1)
  189 + this.initLoadingText = `获取远端数据失败,等待${this.remote_data_refresh_seconds}秒后重新获取,请稍后...`
  190 + this.remoteDataTimer.count++
  191 + })
  192 + },
  193 + refreshDataByRemoteApi () { // 使用后台api刷新数据
  194 + // console.log('refreshDataByRemoteApi')
  195 + // length===0说明初始化失败,或者后台无数据,重新刷新
  196 + if (!this.scrollPageInnerData || !this.scrollPageInnerData.scrollDataItemList.length) {
  197 + this.initDataByRemoteApi()
  198 + } else {
  199 + jsonp(this.remoteUrl).then(remoteDataList => {
  200 + this.scrollPageInnerData.refreshDataWithRemoteData(remoteDataList)
  201 + // console.log('refresh')
  202 + // this.scrollPageInnerData._scrollDataItemList[0]._eBusStopData.showType = 2
  203 + }).catch(err => {
  204 + console.log(err)
  205 + this.$message.error(` 获取数据失败,状态:${err.status},错误:${err.statusText}`, 1)
  206 + })
  207 + this.remoteDataTimer.count++
  208 + }
  209 + }
  210 + }
  211 +}
  212 +
  213 +
  214 +
front-end/h5/src/components/core/plugins/bsth/othergj/linechart/list/othergj-eBusStop-line-chart-list.js 0 → 100644
  1 +/**
  2 + * 自定义线路模拟图组件列表(内部使用 othergj-eBusStop-line-chart 组件)
  3 + */
  4 +
  5 +import PropTypes from '@luban-h5/plugin-common-props'
  6 +
  7 +import scrollPage from 'core/plugins/bsth/othergj/linechart/list/othergj-eBusStop-line-chart-list-scrollPage'
  8 +
  9 +import './css/othergj-eBusStop-line-chart-list.css'
  10 +
  11 +export default {
  12 + extra: {
  13 + defaultStyle: { // 默认属性
  14 + top: 0,
  15 + left: 0,
  16 + width: 700,
  17 + height: 800
  18 + }
  19 + },
  20 + name: 'othergj-eBusStop-line-chart-list',
  21 + data () {
  22 + // eslint-disable-next-line
  23 + this.private_jQuery = jQuery.noConflict() // jquery引用
  24 + return {
  25 + /**
  26 + * 监控外层元素的宽度高度变化
  27 + * 1、由于编辑器缩放,自定义组件无法监控,所以需要定义一个定时器监控最外层元素的大小变化
  28 + * 2、建议所有自定义组件,最外层都定义一个div包在自定义组件最外层,不要关联任何自定义的属性,样式对应编辑器的通用样式
  29 + */
  30 + watchWidthHeightTimer: {
  31 + timer: undefined,
  32 + count: 0,
  33 + millisecond: 1000
  34 + },
  35 + list_width: 350, // 列表组件宽度
  36 + list_height: 300, // 列表组件高度
  37 + line_chart_outer_div_width: 0, // 线路图外层div宽度
  38 + line_chart_outer_div_height: 0, // 线路图外层div高度
  39 + internalDataSet: [], // 内部数据(ScrollPageInnerDataItem类型数组,由数据组件生成)
  40 + scrollTop: 0 // 控制垂直滚动 top
  41 + }
  42 + },
  43 + props: {
  44 + editorMode: PropTypes.string({ // 编辑模式会由编辑器自动注入(值:edit, preview)
  45 + defaultValue: 'preview',
  46 + label: '模式',
  47 + visible: false
  48 + }),
  49 + // --------------- 数据属性 -------------- //
  50 + _flag_1_: PropTypes.string({ label: '', component: null, extra (h) { return (<hr data-label='数据属性' class='bsth-line-item-divider'/>) } }),
  51 + page_size: PropTypes.number({ label: '每页显示线路图数量', defaultValue: 5, layout: { prefixCls: 'bsth-line' } }),
  52 + scroll_seconds: PropTypes.number({ label: '滚动时间间隔(秒)', defaultValue: 30, layout: { prefixCls: 'bsth-line' } }),
  53 + scroll_speed: PropTypes.number({ label: '滚动速度(像素/秒)', defaultValue: 1000000, layout: { prefixCls: 'bsth-line' } }),
  54 + remote_data_refresh_seconds: PropTypes.number({ label: '数据刷新间隔(秒)', defaultValue: 30, layout: { prefixCls: 'bsth-line' } }),
  55 + remote_data_url: PropTypes.string({ label: '远端数据url', component: 'a-textarea', defaultValue: 'http://36.134.151.106:19102/General_Interface/getArriveVO', layout: { prefixCls: 'bsth-line' } }),
  56 + device_id: PropTypes.string({ label: '站牌设备Id', defaultValue: '66MH0001', layout: { prefixCls: 'bsth-line' } }),
  57 + // --------------- 外层css属性 --------------- //
  58 + _flag_2_: PropTypes.string({ label: '', component: null, extra (h) { return (<hr data-label='外层css属性' class='bsth-line-item-divider'/>) } }),
  59 + margin_left: PropTypes.number({ label: '图左边margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),
  60 + margin_right: PropTypes.number({ label: '图右边margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),
  61 + margin_top: PropTypes.number({ label: '图上边margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),
  62 + margin_bottom: PropTypes.number({ label: '图底部margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),
  63 + border_size: PropTypes.number({ label: '图边框宽度', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),
  64 + background_color: PropTypes.color({ label: '背景颜色', defaultValue: '#9EE0DF', layout: { prefixCls: 'bsth-line' } }),
  65 + // --------------- 内部线路模拟图外层css属性 --------------- //
  66 + _flag_3_: PropTypes.string({ label: '', component: null, extra (h) { return (<hr data-label='内部线路模拟图外层css属性' class='bsth-line-item-divider'></hr>) } }),
  67 + line_chart_margin_left: PropTypes.number({ label: '图左边margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),
  68 + line_chart_margin_right: PropTypes.number({ label: '图右边margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),
  69 + line_chart_margin_top: PropTypes.number({ label: '图上边margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),
  70 + line_chart_margin_bottom: PropTypes.number({ label: '图底部margin', defaultValue: 0, layout: { prefixCls: 'bsth-line' } }),
  71 + line_chart_border_size: PropTypes.number({ label: '图边框宽度', defaultValue: 1, layout: { prefixCls: 'bsth-line' } }),
  72 + line_chart_background_color: PropTypes.color({ label: '背景颜色', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }),
  73 + // 图内层css
  74 + _flag_5_: PropTypes.string({ label: '', component: null, extra: function (h) { return (<hr data-label="图内层上部分矩形css属性" class="bsth-line-item-divider"></hr>) } }),
  75 + svg_background: PropTypes.color({ label: '线路图背景颜色', defaultValue: '#9EE0DF', layout: { prefixCls: 'bsth-line' } }),
  76 + chart_left_padding: PropTypes.number({ label: '内部线路图距离左边', defaultValue: 50, layout: { prefixCls: 'bsth-line' } }),
  77 + chart_right_padding: PropTypes.number({ label: '内部线路图距离右边', defaultValue: 50, layout: { prefixCls: 'bsth-line' } }),
  78 + chart_top_padding: PropTypes.number({ label: '内部线路图距离上边', defaultValue: 40, layout: { prefixCls: 'bsth-line' } }),
  79 + chart_up_line_path_s_width: PropTypes.number({ label: '上部分线宽度', defaultValue: 2, layout: { prefixCls: 'bsth-line' } }),
  80 + chart_up_line_path_s_color: PropTypes.color({ label: '上部分线颜色', defaultValue: '#008000', layout: { prefixCls: 'bsth-line' } }),
  81 + chart_up_line_circle_f_color_current: PropTypes.color({ label: '线圆圈填充色-当前站点', defaultValue: '#CB0808', layout: { prefixCls: 'bsth-line' } }),
  82 + chart_up_line_circle_f_color_before: PropTypes.color({ label: '线圆圈填充色-前面站点', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }),
  83 + chart_up_line_circle_f_color_after: PropTypes.color({ label: '线圆圈填充色-后面站点', defaultValue: '#FFFFFF', layout: { prefixCls: 'bsth-line' } }),
  84 + chart_up_line_circle_r: PropTypes.number({ label: '线圆圈大小', defaultValue: 3, layout: { prefixCls: 'bsth-line' } }),
  85 + chart_station_text_top_padding: PropTypes.number({ label: '站点文字距离上边', defaultValue: 50, layout: { prefixCls: 'bsth-line' } }),
  86 + chart_station_text_font_size_current: PropTypes.number({ label: '站名字体大小-当前站点', defaultValue: 12, layout: { prefixCls: 'bsth-line' } }),
  87 + chart_station_text_font_size_before: PropTypes.number({ label: '站名字体大小-前面站点', defaultValue: 12, layout: { prefixCls: 'bsth-line' } }),
  88 + chart_station_text_font_size_after: PropTypes.number({ label: '站名字体大小-后面站点', defaultValue: 12, layout: { prefixCls: 'bsth-line' } }),
  89 + chart_station_text_space: PropTypes.number({ label: '站名间距', defaultValue: 2, layout: { prefixCls: 'bsth-line' } }),
  90 + chart_station_text_transform_second: PropTypes.number({ label: '站名滚动间隔(秒)', defaultValue: 3, layout: { prefixCls: 'bsth-line' } }),
  91 + chart_up_station_text_font_f_color_current: PropTypes.color({ label: '站名颜色-当前站点', defaultValue: '#060D37', layout: { prefixCls: 'bsth-line' } }),
  92 + chart_up_station_text_font_f_color_before: PropTypes.color({ label: '站名颜色-前面站点', defaultValue: '#9398B4', layout: { prefixCls: 'bsth-line' } }),
  93 + chart_up_station_text_font_f_color_after: PropTypes.color({ label: '站名颜色-后面站点', defaultValue: '#4556b6', layout: { prefixCls: 'bsth-line' } }),
  94 + _flag_6_: PropTypes.string({ label: '', component: null, extra: function (h) { return (<hr data-label="图内层下部分线css属性" class="bsth-line-item-divider"></hr>) } }),
  95 + down_line_left_padding: PropTypes.number({ label: '线距离左边', defaultValue: 100, layout: { prefixCls: 'bsth-line' } }),
  96 + down_line_right_padding: PropTypes.number({ label: '线距离右边', defaultValue: 100, layout: { prefixCls: 'bsth-line' } }),
  97 + down_line_bottom_padding: PropTypes.number({ label: '线距离下边', defaultValue: 6, layout: { prefixCls: 'bsth-line' } }),
  98 + down_line_s_width: PropTypes.number({ label: '线宽度', defaultValue: 2, layout: { prefixCls: 'bsth-line' } }),
  99 + down_line_s_color: PropTypes.color({ label: '线颜色', defaultValue: '#277461', layout: { prefixCls: 'bsth-line' } }),
  100 + down_line_arrow_width: PropTypes.number({ label: '箭头宽度', defaultValue: 100, layout: { prefixCls: 'bsth-line' } }),
  101 + down_line_arrow_height: PropTypes.number({ label: '箭头高度', defaultValue: 15, layout: { prefixCls: 'bsth-line' } }),
  102 + _flag_7_: PropTypes.string({ label: '', component: null, extra: function (h) { return (<hr data-label="无数据提示css属性" class="bsth-line-item-divider"></hr>) } }),
  103 + empty_info_font_size: PropTypes.number({ label: '无数据提示文字字体大小', defaultValue: 30, layout: { prefixCls: 'bsth-line' } }),
  104 + empty_info_font_color: PropTypes.color({ label: '无数据提示文字字体颜色', defaultValue: '#000000', layout: { prefixCls: 'bsth-line' } }),
  105 + empty_info_top_padding: PropTypes.number({ label: '无数据提示文字距离上边', defaultValue: 25, layout: { prefixCls: 'bsth-line' } })
  106 + },
  107 + render () {
  108 + /* 最外层div对应编辑器的通用样式 */
  109 + return (
  110 + <div class="othergj-eBusStop-line-chart-list-outer-div">
  111 + {
  112 + this.renderScrollPage()
  113 + }
  114 + </div>
  115 + )
  116 + },
  117 + mounted () {
  118 + // 使用外部元素的框架定义图的长宽
  119 + let $jQuery = this.private_jQuery
  120 + this.list_width = $jQuery(this.$el).width() - this.margin_left - this.margin_right
  121 + this.list_height = $jQuery(this.$el).height() - this.margin_top - this.margin_bottom
  122 + // 开启外部元素长宽监控计数
  123 + /**
  124 + * 开启外部元素长宽监控逻辑
  125 + * 1、必须在编辑模式下启效果,否则无效
  126 + */
  127 + if (this.editorMode === 'edit') {
  128 + this.watchWidthHeightTimer.count++
  129 + }
  130 + },
  131 + destroyed () {
  132 + // 消耗 watchWidthHeightTimer 定时器
  133 + let timer1 = this.watchWidthHeightTimer.timer
  134 + if (timer1) {
  135 + try {
  136 + clearTimeout(timer1)
  137 + } catch (e) {}
  138 + this.watchWidthHeightTimer.timer = undefined
  139 + }
  140 + },
  141 + watch: {
  142 + 'watchWidthHeightTimer.count' () { // 长宽定时器监控
  143 + let timer = this.watchWidthHeightTimer.timer
  144 + if (timer) {
  145 + clearTimeout(timer)
  146 + this.watchWidthHeightTimer.timer = null
  147 + }
  148 +
  149 + let self = this
  150 + let $jQuery = this.private_jQuery
  151 + self.watchWidthHeightTimer.timer = setTimeout(function () {
  152 + // 处理逻辑
  153 + let width = $jQuery(self.$el).width()
  154 + let height = $jQuery(self.$el).height()
  155 +
  156 + if (width !== self.list_width) {
  157 + self.list_width = width - self.margin_left - self.margin_right
  158 + }
  159 + if (height !== self.list_height) {
  160 + self.list_height = height - self.margin_top - self.margin_bottom
  161 + }
  162 +
  163 + self.watchWidthHeightTimer.count++
  164 + }, self.watchWidthHeightTimer.millisecond)
  165 + },
  166 + // ----------------- 数据属性 ---------------- //
  167 + page_size () {
  168 + this.line_chart_outer_div_height = Math.floor(this.list_height / this.page_size)
  169 + },
  170 + // ----------------- 本身宽高 监控 ---------------- //
  171 + list_width () {
  172 + this.line_chart_outer_div_width = this.list_width - this.border_size * 2
  173 + },
  174 + list_height () {
  175 + this.line_chart_outer_div_height = Math.floor((this.list_height - this.border_size * 2) / this.page_size)
  176 + },
  177 + // ----------------- 外层css属性 监控 ----------------- //
  178 + margin_left () {
  179 + this.list_width = this.list_width - this.margin_left - this.margin_right
  180 + },
  181 + margin_right () {
  182 + this.list_width = this.list_width - this.margin_left - this.margin_right
  183 + },
  184 + margin_top () {
  185 + this.list_height = this.list_height - this.margin_top - this.margin_bottom
  186 + },
  187 + margin_bottom () {
  188 + this.list_height = this.list_height - this.margin_top - this.margin_bottom
  189 + },
  190 + border_size () {
  191 + this.line_chart_outer_div_width = this.list_width - this.border_size * 2
  192 + this.line_chart_outer_div_height = Math.floor((this.list_height - this.border_size * 2) / this.page_size)
  193 + }
  194 + },
  195 + methods: {
  196 + /**
  197 + * scrollPage组件的scrollTop事件处理函数。
  198 + * @param val 视口距离内部page的距离
  199 + */
  200 + onScrollTop (val) {
  201 + // 注意:默认向上滚动,scrollPage组件内部的view视口是向下移动的,top是大于等于0的
  202 + // 但是,使用scrollPage的组件外部view视口div是固定的,只能移动内部的div,所以top要变成负值
  203 + if (val === 0) {
  204 + this.scrollTop = 0
  205 + } else {
  206 + this.scrollTop = -val
  207 + }
  208 + },
  209 + /**
  210 + * scrollPage组件的bindData事件处理函数。
  211 + * @param dataSet
  212 + */
  213 + onBindData (dataSet) {
  214 + // 初始化的时候绑定一次数据,之后所有数据的变化都在ScrollPage内部变化
  215 + this.internalDataSet = dataSet
  216 + },
  217 +
  218 + /**
  219 + * 绘制scrollPage组件(内部组件,只能在本组件中使用,index.js中未注册)。
  220 + * @return {*}
  221 + */
  222 + renderScrollPage () {
  223 + const innerDivStyle = {
  224 + 'width': this.list_width + 'px',
  225 + 'height': this.list_height + 'px',
  226 + 'border': this.border_size + 'px solid black',
  227 + 'margin-left': this.margin_left + 'px',
  228 + 'margin-right': this.margin_right + 'px',
  229 + 'margin-top': this.margin_top + 'px',
  230 + 'margin-bottom': this.margin_bottom + 'px',
  231 + 'background': this.background_color,
  232 + 'position': 'relative',
  233 + 'overflow': 'hidden' // 隐藏超出的模拟图
  234 + }
  235 +
  236 + // 包含所有的线路模拟图,滚动时设置top值,总高度等于所有图高度和
  237 + const wrapperDivStyle = {
  238 + 'top': this.scrollTop + 'px',
  239 + 'position': 'absolute',
  240 + 'width': this.list_width + 'px',
  241 + 'height': this.line_chart_outer_div_height * this.internalDataSet.length + 'px'
  242 + }
  243 +
  244 + return (
  245 + <scrollPage
  246 + editorMode={this.editorMode}
  247 + page_size={this.page_size}
  248 + list_width={this.list_width}
  249 + list_height={this.list_height}
  250 + scroll_seconds={this.scroll_seconds}
  251 + scroll_speed={this.scroll_speed}
  252 + remote_data_url={this.remote_data_url}
  253 + remote_data_url_param_device_id={this.device_id}
  254 + remote_data_refresh_seconds={this.remote_data_refresh_seconds}
  255 + onBindData={this.onBindData}
  256 + onScrollTop={this.onScrollTop}>
  257 + <div style={innerDivStyle}>
  258 + <div style={wrapperDivStyle}>
  259 + {
  260 + this.internalDataSet.map(dataItem => (
  261 + this.renderLineChart(dataItem._eBusStopData)
  262 + ))
  263 + }
  264 + </div>
  265 + </div>
  266 + </scrollPage>
  267 + )
  268 + },
  269 + /**
  270 + * 绘制eBusStop-line-chart组件(index.js中已经注册过,不需要import)。
  271 + * @param eBusStopData EBusStopData类型
  272 + * @return {*}
  273 + */
  274 + renderLineChart (eBusStopData) {
  275 + return (
  276 + <othergj-eBusStop-line-chart
  277 + useMode='child'
  278 + editorMode={this.editorMode}
  279 + line_chart_outer_div_width={this.line_chart_outer_div_width}
  280 + line_chart_outer_div_height={this.line_chart_outer_div_height}
  281 + eBusStopData_child={eBusStopData}
  282 + // 内部线路模拟图外层css属性
  283 + margin_left={this.line_chart_margin_left}
  284 + margin_right={this.line_chart_margin_right}
  285 + margin_top={this.line_chart_margin_top}
  286 + margin_bottom={this.line_chart_margin_bottom}
  287 + border_size={this.line_chart_border_size}
  288 + background_color={this.line_chart_background_color}
  289 + // 内部线路模拟图内层css属性
  290 + svg_background={this.svg_background}
  291 + chart_left_padding={this.chart_left_padding}
  292 + chart_right_padding={this.chart_right_padding}
  293 + chart_top_padding={this.chart_top_padding}
  294 + chart_up_line_path_s_width={this.chart_up_line_path_s_width}
  295 + chart_up_line_path_s_color={this.chart_up_line_path_s_color}
  296 + chart_up_line_circle_f_color_current={this.chart_up_line_circle_f_color_current}
  297 + chart_up_line_circle_f_color_before={this.chart_up_line_circle_f_color_before}
  298 + chart_up_line_circle_f_color_after={this.chart_up_line_circle_f_color_after}
  299 + chart_up_line_circle_r={this.chart_up_line_circle_r}
  300 + chart_station_text_top_padding={this.chart_station_text_top_padding}
  301 + chart_station_text_font_size_current={this.chart_station_text_font_size_current}
  302 + chart_station_text_font_size_before={this.chart_station_text_font_size_before}
  303 + chart_station_text_font_size_after={this.chart_station_text_font_size_after}
  304 + chart_station_text_space={this.chart_station_text_space}
  305 + chart_station_text_transform_second={this.chart_station_text_transform_second}
  306 + chart_up_station_text_font_f_color_current={this.chart_up_station_text_font_f_color_current}
  307 + chart_up_station_text_font_f_color_before={this.chart_up_station_text_font_f_color_before}
  308 + chart_up_station_text_font_f_color_after={this.chart_up_station_text_font_f_color_after}
  309 + down_line_left_padding={this.down_line_left_padding}
  310 + down_line_right_padding={this.down_line_right_padding}
  311 + down_line_bottom_padding={this.down_line_bottom_padding}
  312 + down_line_s_width={this.down_line_s_width}
  313 + down_line_s_color={this.down_line_s_color}
  314 + down_line_arrow_width={this.down_line_arrow_width}
  315 + down_line_arrow_height={this.down_line_arrow_height}
  316 + empty_info_font_size={this.empty_info_font_size}
  317 + empty_info_font_color={this.empty_info_font_color}
  318 + empty_info_top_padding={this.empty_info_top_padding}
  319 + />
  320 + )
  321 + }
  322 + }
  323 +}
front-end/h5/src/components/core/plugins/index.js
@@ -34,6 +34,7 @@ import MhgjEBusStopLineChart from &#39;core/plugins/bsth/mhgj/chart/mhgj-eBusStop-li @@ -34,6 +34,7 @@ import MhgjEBusStopLineChart from &#39;core/plugins/bsth/mhgj/chart/mhgj-eBusStop-li
34 import MhgjEBusStopLineChartList from 'core/plugins/bsth/mhgj/list/mhgj-eBusStop-line-chart-list' 34 import MhgjEBusStopLineChartList from 'core/plugins/bsth/mhgj/list/mhgj-eBusStop-line-chart-list'
35 35
36 import OthergjEBusStopLineChart from 'core/plugins/bsth/othergj/linechart/chart/othergj-eBusStop-line-chart' 36 import OthergjEBusStopLineChart from 'core/plugins/bsth/othergj/linechart/chart/othergj-eBusStop-line-chart'
  37 +import OthergjEBusStopLineChartList from 'core/plugins/bsth/othergj/linechart/list/othergj-eBusStop-line-chart-list'
37 38
38 export const pluginsList = [ 39 export const pluginsList = [
39 // { 40 // {
@@ -353,7 +354,7 @@ export const pluginsList = [ @@ -353,7 +354,7 @@ export const pluginsList = [
353 title: '电子站牌单线路模拟图2', 354 title: '电子站牌单线路模拟图2',
354 icon: 'list', 355 icon: 'list',
355 component: MhgjEBusStopLineChart, 356 component: MhgjEBusStopLineChart,
356 - visible: true, 357 + visible: false,
357 name: MhgjEBusStopLineChart.name 358 name: MhgjEBusStopLineChart.name
358 }, 359 },
359 360
@@ -377,10 +378,21 @@ export const pluginsList = [ @@ -377,10 +378,21 @@ export const pluginsList = [
377 title: '电子站牌单线路模拟图3', 378 title: '电子站牌单线路模拟图3',
378 icon: 'list', 379 icon: 'list',
379 component: OthergjEBusStopLineChart, 380 component: OthergjEBusStopLineChart,
380 - visible: false, 381 + visible: true,
381 name: OthergjEBusStopLineChart.name 382 name: OthergjEBusStopLineChart.name
382 }, 383 },
383 384
  385 + {
  386 + i18nTitle: {
  387 + 'en-US': 'OthergjEBusStopLineChartList',
  388 + 'zh-CN': '电子站牌单线路模拟图3list'
  389 + },
  390 + title: '电子站牌单线路模拟图3list',
  391 + icon: 'list',
  392 + component: OthergjEBusStopLineChartList,
  393 + visible: true,
  394 + name: OthergjEBusStopLineChartList.name
  395 + },
384 396
385 // { 397 // {
386 // i18nTitle: { 398 // i18nTitle: {