Commit 1e8c4d434ddee11b67ed31ca1f74978f51da7588
1 parent
09b8a3f5
其他公交公司用的公交电子站牌页面组件
1、新建othergj/linechart/chart目录,添加othergj-eBusStop-line-chart-list相关组件
Showing
5 changed files
with
1504 additions
and
1 deletions
front-end/h5/src/components/core/plugins/bsth/othergj/linechart/chart/bak.js
0 → 100644
| 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/css/othergj-eBusStop-line-chart.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-outer-div, .othergj-eBusStop-line-chart-outer-div * { | ||
| 9 | + box-sizing: border-box; | ||
| 10 | +} | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + 电子站牌线路模拟图使用的css | ||
| 14 | + */ | ||
| 15 | +svg.othergj-eBusStop-line-chart { | ||
| 16 | + width: 100%; | ||
| 17 | + height: 100%; | ||
| 18 | + position: absolute; | ||
| 19 | + left: 0; | ||
| 20 | + | ||
| 21 | + /* 文本css */ | ||
| 22 | + font-style: normal; | ||
| 23 | + font-variant-ligatures: normal; | ||
| 24 | + font-variant-caps: normal; | ||
| 25 | + font-variant-numeric: normal; | ||
| 26 | + font-variant-east-asian: normal; | ||
| 27 | + font-weight: 400; | ||
| 28 | + font-stretch: normal; | ||
| 29 | + font-size: 14px; | ||
| 30 | + line-height: 20px; | ||
| 31 | + font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; | ||
| 32 | +} | ||
| 33 | + | ||
| 34 | +svg.othergj-eBusStop-line-chart path.station_link { | ||
| 35 | + stroke-width: 3.5; | ||
| 36 | + stroke: #5E96D2; | ||
| 37 | + Pointer-events: none; | ||
| 38 | +} | ||
| 39 | + | ||
| 40 | +svg.othergj-eBusStop-line-chart circle.station_circle { | ||
| 41 | + fill: #5e96d2; | ||
| 42 | + /*r: 5.5;*/ | ||
| 43 | + stroke: rgb(253, 253, 253); | ||
| 44 | + stroke-width: 3; | ||
| 45 | + Pointer-events: none; | ||
| 46 | +} | ||
| 47 | + | ||
| 48 | +svg.othergj-eBusStop-line-chart text.station_text { | ||
| 49 | + writing-mode: tb; | ||
| 50 | + fill: #3e3e3e; | ||
| 51 | + letter-spacing: -.2px; | ||
| 52 | + text-shadow: 0 0 2px #dadada; | ||
| 53 | + Pointer-events: none; | ||
| 54 | +} | ||
| 55 | + | ||
| 56 | +svg.othergj-eBusStop-line-chart text.station_text.up { | ||
| 57 | + fill: #4556b6; | ||
| 58 | +} | ||
| 59 | + | ||
| 60 | + | ||
| 61 | + |
front-end/h5/src/components/core/plugins/bsth/othergj/linechart/chart/models/eBusStopData.js
0 → 100644
| 1 | +/** | ||
| 2 | + * 公交线路模拟图组件用数据。 | ||
| 3 | + */ | ||
| 4 | + | ||
| 5 | +// 站点信息 | ||
| 6 | +class StationData { | ||
| 7 | + /** | ||
| 8 | + * 构造函数。 | ||
| 9 | + * @param name 站点名字 | ||
| 10 | + * @param code 站点编码 | ||
| 11 | + */ | ||
| 12 | + constructor (name, code) { | ||
| 13 | + this._name = name | ||
| 14 | + this._code = code | ||
| 15 | + } | ||
| 16 | + | ||
| 17 | + get name () { | ||
| 18 | + return this._name | ||
| 19 | + } | ||
| 20 | + get code () { | ||
| 21 | + return this._code | ||
| 22 | + } | ||
| 23 | +} | ||
| 24 | +// 路由信息 | ||
| 25 | +class RouteData { | ||
| 26 | + /** | ||
| 27 | + * 构造函数。 | ||
| 28 | + * @param stopStationIndex 当前站牌对应站点索引 | ||
| 29 | + * @param stationDataList 所有站点列表(StationData类型) | ||
| 30 | + */ | ||
| 31 | + constructor (stopStationIndex, stationDataList = []) { | ||
| 32 | + this._stopStationIndex = stopStationIndex | ||
| 33 | + this._stationDataList = [...stationDataList] | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + get index () { | ||
| 37 | + return this._stopStationIndex | ||
| 38 | + } | ||
| 39 | + get dataList () { | ||
| 40 | + return this._stationDataList | ||
| 41 | + } | ||
| 42 | +} | ||
| 43 | + | ||
| 44 | +// 电子站牌信息 | ||
| 45 | +class EBusStopData { | ||
| 46 | + /** | ||
| 47 | + * 构造函数。 | ||
| 48 | + * @param lineName 线路名称 | ||
| 49 | + * @param lineCode 线路编码 | ||
| 50 | + * @param routeData 路由信息(RouteData类型) | ||
| 51 | + * @param startTime 首班车时间字符串(格式: HH:mm) | ||
| 52 | + * @param endTime 末班车时间字符串(格式:HH:mm) | ||
| 53 | + */ | ||
| 54 | + constructor (lineName, lineCode, routeData, startTime = '00:00', endTime = '23:59') { | ||
| 55 | + this._lineName = lineName | ||
| 56 | + this._lineCode = lineCode | ||
| 57 | + this._routeData = routeData | ||
| 58 | + this._startTime = startTime | ||
| 59 | + this._endTime = endTime | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + /** | ||
| 63 | + * 获取线路名称。 | ||
| 64 | + * @return {*} | ||
| 65 | + */ | ||
| 66 | + get lineName () { | ||
| 67 | + return this._lineName | ||
| 68 | + } | ||
| 69 | + /** | ||
| 70 | + * 获取线路编码。 | ||
| 71 | + * @return {*} | ||
| 72 | + */ | ||
| 73 | + get lineCode () { | ||
| 74 | + return this._lineCode | ||
| 75 | + } | ||
| 76 | + /** | ||
| 77 | + * 获取路由站点列表。 | ||
| 78 | + */ | ||
| 79 | + get routeStationDataList () { | ||
| 80 | + return this._routeData.dataList | ||
| 81 | + } | ||
| 82 | + /** | ||
| 83 | + * 获取当前站点在路由中的索引。 | ||
| 84 | + */ | ||
| 85 | + get currentStopStationIndex () { | ||
| 86 | + return this._routeData.index | ||
| 87 | + } | ||
| 88 | + /** | ||
| 89 | + * 获取当前路由的终点站。 | ||
| 90 | + * @return {string} | ||
| 91 | + */ | ||
| 92 | + get endStationName () { | ||
| 93 | + if (this._routeData.dataList.length > 0) { | ||
| 94 | + return this._routeData.dataList.slice(-1)[0].name | ||
| 95 | + } else { | ||
| 96 | + return '' | ||
| 97 | + } | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + /** | ||
| 101 | + * 获取首班车时间。 | ||
| 102 | + */ | ||
| 103 | + get startTime () { | ||
| 104 | + return this._startTime | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + /** | ||
| 108 | + * 获取末班车时间。 | ||
| 109 | + */ | ||
| 110 | + get endTime () { | ||
| 111 | + return this._endTime | ||
| 112 | + } | ||
| 113 | + | ||
| 114 | + /** | ||
| 115 | + * 产生测试数据。 | ||
| 116 | + */ | ||
| 117 | + static generateTestData () { | ||
| 118 | + // 1、站点信息 | ||
| 119 | + let s1 = new StationData('站点1', '1') | ||
| 120 | + let s2 = new StationData('站点2', '2') | ||
| 121 | + let s3 = new StationData('站点3', '3') | ||
| 122 | + let s4 = new StationData('站点4', '4') | ||
| 123 | + let s5 = new StationData('站点5', '5') | ||
| 124 | + let s6 = new StationData('站点6', '6') | ||
| 125 | + let stationDataList = [s1, s2, s3, s4, s5, s6] | ||
| 126 | + // 2、路由信息 | ||
| 127 | + let routeData = new RouteData(2, stationDataList) | ||
| 128 | + // 3、电子站牌信息 | ||
| 129 | + return new EBusStopData('线路1', '1', routeData) | ||
| 130 | + } | ||
| 131 | + | ||
| 132 | + /** | ||
| 133 | + * 产生空测试数据。 | ||
| 134 | + */ | ||
| 135 | + static generateTestData_null () { | ||
| 136 | + return new EBusStopData('', '', new RouteData(0, [])) | ||
| 137 | + } | ||
| 138 | + | ||
| 139 | +} | ||
| 140 | + | ||
| 141 | +export { | ||
| 142 | + StationData, | ||
| 143 | + RouteData, | ||
| 144 | + EBusStopData | ||
| 145 | +} |
front-end/h5/src/components/core/plugins/bsth/othergj/linechart/chart/othergj-eBusStop-line-chart.js
0 → 100644
| 1 | +/** | ||
| 2 | + * 自定义线路模拟图组件(临港公交电子站牌使用) | ||
| 3 | + */ | ||
| 4 | +import PropTypes from '@luban-h5/plugin-common-props' | ||
| 5 | + | ||
| 6 | +import Utils from 'core/plugins/bsth/bsth-utils' | ||
| 7 | +import { EBusStopData } from 'core/plugins/bsth/othergj/linechart/chart/models/eBusStopData' | ||
| 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 | + // this.private_up_rect_wrap_svg = null // 创建包含矩形最外层g元素 | ||
| 27 | + // eslint-disable-next-line | ||
| 28 | + this.private_jQuery = jQuery.noConflict() // jquery引用 | ||
| 29 | + // eslint-disable-next-line | ||
| 30 | + this.private_d3 = d3 // d3引用 | ||
| 31 | + | ||
| 32 | + return { | ||
| 33 | + /** | ||
| 34 | + * 监控外层元素的宽度高度变化 | ||
| 35 | + * 1、由于编辑器缩放,自定义组件无法监控,所以需要定义一个定时器监控最外层元素的大小变化 | ||
| 36 | + * 2、建议所有自定义组件,最外层都定义一个div包在自定义组件最外层,不要关联任何自定义的属性,样式对应编辑器的通用样式 | ||
| 37 | + */ | ||
| 38 | + watchWidthHeightTimer: { | ||
| 39 | + timer: null, | ||
| 40 | + count: 0, | ||
| 41 | + millisecond: 1000 | ||
| 42 | + }, | ||
| 43 | + | ||
| 44 | + // TODO:其他timer | ||
| 45 | + | ||
| 46 | + // 注意:css里设定了box-sizing: border-box;,所以组件本身的宽高包括了margin,padding,border | ||
| 47 | + // 所以计算内部其他组件宽高需要减去margin,padding,border | ||
| 48 | + component_width: 350, // 组件宽度 | ||
| 49 | + component_height: 400, // 组件高度 | ||
| 50 | + svg_width: 350, // 图宽度 | ||
| 51 | + svg_height: 300, // 图高度 | ||
| 52 | + | ||
| 53 | + // TODO:其他属性 | ||
| 54 | + | ||
| 55 | + // svg内部下部分线的属性(mounted初始计算一次) | ||
| 56 | + down_line_x1: 0, | ||
| 57 | + down_line_y1: 0, | ||
| 58 | + down_line_x2: 0, | ||
| 59 | + down_line_y2: 0, | ||
| 60 | + down_line_x3: 0, | ||
| 61 | + down_line_y3: 0, | ||
| 62 | + down_line_x4: 0, | ||
| 63 | + down_line_y4: 0, | ||
| 64 | + down_line_x5: 0, | ||
| 65 | + down_line_y5: 0, | ||
| 66 | + | ||
| 67 | + eBusStopData: null // 电子站牌数据(EBusStopData类型) | ||
| 68 | + } | ||
| 69 | + }, | ||
| 70 | + computed: { | ||
| 71 | + // TODO: | ||
| 72 | + }, | ||
| 73 | + props: { | ||
| 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: EBusStopData, | ||
| 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 | + // 图内层css | ||
| 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.svg_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 | + | ||
| 200 | + </div> | ||
| 201 | + </div> | ||
| 202 | + ) | ||
| 203 | + }, | ||
| 204 | + beforeMount () { | ||
| 205 | + // 设置数据 | ||
| 206 | + if (this.useMode === 'alone') { // 单独使用,使用测试数据 | ||
| 207 | + this.eBusStopData = EBusStopData.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 | + component_width () { | ||
| 306 | + this.svg_width = this.component_width - this.border_size * 2 | ||
| 307 | + }, | ||
| 308 | + component_height () { | ||
| 309 | + this.svg_height = this.component_height - this.border_size * 2 | ||
| 310 | + }, | ||
| 311 | + | ||
| 312 | + svg_width () { | ||
| 313 | + this.refreshLineSvg() | ||
| 314 | + this.refreshDownLineSvg() | ||
| 315 | + }, | ||
| 316 | + svg_height () { | ||
| 317 | + this.refreshLineSvg() | ||
| 318 | + this.refreshDownLineSvg() | ||
| 319 | + }, | ||
| 320 | + // ----------- 图外层css 监控 ----------- // | ||
| 321 | + margin_left () { | ||
| 322 | + let self = this | ||
| 323 | + self.component_width = self.component_width - self.margin_left - self.margin_right | ||
| 324 | + }, | ||
| 325 | + margin_right () { | ||
| 326 | + let self = this | ||
| 327 | + self.component_width = self.component_width - self.margin_left - self.margin_right | ||
| 328 | + }, | ||
| 329 | + margin_top () { | ||
| 330 | + let self = this | ||
| 331 | + self.component_height = self.component_height - self.margin_top - self.margin_bottom | ||
| 332 | + }, | ||
| 333 | + margin_bottom () { | ||
| 334 | + let self = this | ||
| 335 | + self.component_height = self.component_height - self.margin_top - self.margin_bottom | ||
| 336 | + }, | ||
| 337 | + border_size () { | ||
| 338 | + 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 | ||
| 340 | + | ||
| 341 | + }, | ||
| 342 | + | ||
| 343 | + // ----------- 图内层css 监控 ----------- // | ||
| 344 | + // ----------- _flag_5_属性 -------------// | ||
| 345 | + chart_left_padding: function () { | ||
| 346 | + this.refreshLineSvg() | ||
| 347 | + }, | ||
| 348 | + chart_right_padding: function () { | ||
| 349 | + this.refreshLineSvg() | ||
| 350 | + }, | ||
| 351 | + chart_top_padding: function () { | ||
| 352 | + this.refreshLineSvg() | ||
| 353 | + }, | ||
| 354 | + chart_up_line_path_s_width: function (val) { | ||
| 355 | + let svg = this.private_svg | ||
| 356 | + svg.selectAll('g.item path.station_link:not(.down)') | ||
| 357 | + .style('stroke-width', val) | ||
| 358 | + }, | ||
| 359 | + chart_up_line_path_s_color: function (val) { | ||
| 360 | + let svg = this.private_svg | ||
| 361 | + svg.selectAll('g.item path.station_link:not(.down)') | ||
| 362 | + .style('stroke', val) | ||
| 363 | + }, | ||
| 364 | + chart_up_line_circle_f_color_current: function (val) { | ||
| 365 | + let svg = this.private_svg | ||
| 366 | + svg.selectAll('g.item circle.station_circle.current') | ||
| 367 | + .style('fill', val) | ||
| 368 | + }, | ||
| 369 | + chart_up_line_circle_f_color_before: function (val) { | ||
| 370 | + let svg = this.private_svg | ||
| 371 | + svg.selectAll('g.item circle.station_circle.before') | ||
| 372 | + .style('fill', val) | ||
| 373 | + }, | ||
| 374 | + chart_up_line_circle_f_color_after: function (val) { | ||
| 375 | + let svg = this.private_svg | ||
| 376 | + svg.selectAll('g.item circle.station_circle.after') | ||
| 377 | + .style('fill', val) | ||
| 378 | + }, | ||
| 379 | + chart_up_line_circle_r: function (val) { | ||
| 380 | + let svg = this.private_svg | ||
| 381 | + svg.selectAll('g.item circle.station_circle') | ||
| 382 | + .style('r', val) | ||
| 383 | + }, | ||
| 384 | + chart_station_text_top_padding: function (val) { | ||
| 385 | + this.refreshLineSvg() | ||
| 386 | + }, | ||
| 387 | + chart_station_text_font_size_current: function (val) { | ||
| 388 | + let svg = this.private_svg | ||
| 389 | + svg.selectAll('g.item text.station_text.up.current') | ||
| 390 | + .style('font-size', val) | ||
| 391 | + }, | ||
| 392 | + chart_station_text_font_size_before: function (val) { | ||
| 393 | + let svg = this.private_svg | ||
| 394 | + svg.selectAll('g.item text.station_text.up.before') | ||
| 395 | + .style('font-size', val) | ||
| 396 | + }, | ||
| 397 | + chart_station_text_font_size_after: function (val) { | ||
| 398 | + let svg = this.private_svg | ||
| 399 | + svg.selectAll('g.item text.station_text.up.after') | ||
| 400 | + .style('font-size', val) | ||
| 401 | + }, | ||
| 402 | + chart_station_text_length: function (val) { | ||
| 403 | + let svg = this.private_svg | ||
| 404 | + svg.selectAll('g.item text') | ||
| 405 | + .attr('textLength', val) | ||
| 406 | + }, | ||
| 407 | + chart_up_station_text_font_f_color_current: function (val) { | ||
| 408 | + let svg = this.private_svg | ||
| 409 | + svg.selectAll('g.item text.station_text.up.current') | ||
| 410 | + .style('stroke', val) | ||
| 411 | + }, | ||
| 412 | + chart_up_station_text_font_f_color_before: function (val) { | ||
| 413 | + let svg = this.private_svg | ||
| 414 | + svg.selectAll('g.item text.station_text.up.before') | ||
| 415 | + .style('stroke', val) | ||
| 416 | + }, | ||
| 417 | + chart_up_station_text_font_f_color_after: function (val) { | ||
| 418 | + let svg = this.private_svg | ||
| 419 | + svg.selectAll('g.item text.station_text.up.after') | ||
| 420 | + .style('stroke', val) | ||
| 421 | + }, | ||
| 422 | + // ----------- _flag_6_属性 ------------- // | ||
| 423 | + down_line_left_padding: function () { | ||
| 424 | + this.refreshDownLineSvg() | ||
| 425 | + }, | ||
| 426 | + down_line_right_padding: function () { | ||
| 427 | + this.refreshDownLineSvg() | ||
| 428 | + }, | ||
| 429 | + down_line_bottom_padding: function () { | ||
| 430 | + this.refreshDownLineSvg() | ||
| 431 | + }, | ||
| 432 | + down_line_s_width: function () { | ||
| 433 | + this.refreshDownLineSvg() | ||
| 434 | + }, | ||
| 435 | + down_line_arrow_width: function () { | ||
| 436 | + this.refreshDownLineSvg() | ||
| 437 | + }, | ||
| 438 | + down_line_arrow_height: function () { | ||
| 439 | + this.refreshDownLineSvg() | ||
| 440 | + } | ||
| 441 | + // ----------- _flag_7_属性 ------------- // | ||
| 442 | + // TODO: | ||
| 443 | + }, | ||
| 444 | + methods: { | ||
| 445 | + findD3SvgDom () { | ||
| 446 | + let $jQuery = this.private_jQuery | ||
| 447 | + let d3 = this.private_d3 | ||
| 448 | + let svgDom = $jQuery(this.$el).find('svg')[0] | ||
| 449 | + return d3.select(svgDom) | ||
| 450 | + }, | ||
| 451 | + refreshDownLineSvg () { | ||
| 452 | + let self = this | ||
| 453 | + | ||
| 454 | + let width = self.svg_width // 内部整个svg的宽度 | ||
| 455 | + let height = self.svg_height // 内部整个svg的高度 | ||
| 456 | + | ||
| 457 | + // 计算svg内部下部分线的属性 | ||
| 458 | + // 5个点,左边两个点作为起点(两个起点用来模拟宽度,如果使用stroke-width,右边箭头无法是夹的),右边3个点组成半个箭头 | ||
| 459 | + // 最左边起点(左下) | ||
| 460 | + this.down_line_x1 = self.down_line_left_padding | ||
| 461 | + this.down_line_y1 = height - self.down_line_bottom_padding | ||
| 462 | + // 最右边箭头起点 | ||
| 463 | + this.down_line_x2 = width - self.down_line_right_padding | ||
| 464 | + this.down_line_y2 = this.down_line_y1 | ||
| 465 | + // 箭头左上角 | ||
| 466 | + this.down_line_x3 = this.down_line_x2 - self.down_line_arrow_width | ||
| 467 | + this.down_line_y3 = this.down_line_y2 - self.down_line_arrow_height - self.down_line_s_width | ||
| 468 | + // 箭头左下角 | ||
| 469 | + this.down_line_x4 = this.down_line_x3 | ||
| 470 | + this.down_line_y4 = this.down_line_y2 - self.down_line_s_width | ||
| 471 | + // 最左边起点(右下) | ||
| 472 | + this.down_line_x5 = this.down_line_x1 | ||
| 473 | + this.down_line_y5 = this.down_line_y4 | ||
| 474 | + }, | ||
| 475 | + refreshLineSvg () { | ||
| 476 | + let self = this | ||
| 477 | + | ||
| 478 | + // let $jQuery = self.private_jQuery | ||
| 479 | + let d3 = self.private_d3 | ||
| 480 | + | ||
| 481 | + let routeData = self.eBusStopData.routeStationDataList | ||
| 482 | + let width = self.svg_width // 内部整个svg的宽度 | ||
| 483 | + // let height = self.svg_height // 内部整个svg的高度 | ||
| 484 | + // let svgNameSpace = self.private_svgns | ||
| 485 | + let svg = self.private_svg | ||
| 486 | + let chartLeftPadding = self.chart_left_padding | ||
| 487 | + let chartRightPadding = self.chart_right_padding | ||
| 488 | + let chartTopPadding = self.chart_top_padding | ||
| 489 | + let chartStopNameTopPadding = self.chart_station_text_top_padding | ||
| 490 | + | ||
| 491 | + // ------------ 1、添加g元素 ---------- // | ||
| 492 | + let itemsUpdate = svg.selectAll('g.item') | ||
| 493 | + .data(routeData, function (d) { | ||
| 494 | + return d.code | ||
| 495 | + }) | ||
| 496 | + let itemsEnter = itemsUpdate | ||
| 497 | + let itemsExit = itemsUpdate.exit() | ||
| 498 | + | ||
| 499 | + itemsExit.remove() | ||
| 500 | + itemsEnter = itemsEnter.enter().append('g').classed('item', true) | ||
| 501 | + | ||
| 502 | + // 创建x轴比例尺 | ||
| 503 | + let xScale = d3.scaleLinear() | ||
| 504 | + .domain([0, routeData.length - 1]) // 定义域 | ||
| 505 | + .range([chartLeftPadding, width - chartRightPadding]) // 值域 | ||
| 506 | + | ||
| 507 | + // ------------ 2、添加/更新线路图上部分的的path元素 ---------- // | ||
| 508 | + let upLineFun = d3.line() | ||
| 509 | + .x(xScale) | ||
| 510 | + .y(function () { | ||
| 511 | + return chartTopPadding | ||
| 512 | + }) | ||
| 513 | + itemsEnter.append('path') | ||
| 514 | + .classed('station_link', true) | ||
| 515 | + .style('stroke', self.chart_up_line_path_s_color) | ||
| 516 | + .style('stroke-width', self.chart_up_line_path_s_width) | ||
| 517 | + .attr('d', function (d, i) { | ||
| 518 | + return i < routeData.length - 1 ? upLineFun([i, i + 1]) : '' | ||
| 519 | + }) | ||
| 520 | + itemsUpdate.select('path') | ||
| 521 | + .attr('d', function (d, i) { | ||
| 522 | + return i < routeData.length - 1 ? upLineFun([i, i + 1]) : '' | ||
| 523 | + }) | ||
| 524 | + | ||
| 525 | + // ------------ 3、添加/更新线路图上部分的circle元素 ---------- // | ||
| 526 | + itemsEnter.select(function (d) { | ||
| 527 | + return d.type !== 1 ? this : null | ||
| 528 | + }).append('circle') | ||
| 529 | + .classed('station_circle', true) | ||
| 530 | + .classed('current', function (d, i) { | ||
| 531 | + return self.eBusStopData.currentStopStationIndex === i | ||
| 532 | + }) | ||
| 533 | + .classed('before', function (d, i) { | ||
| 534 | + return i < self.eBusStopData.currentStopStationIndex | ||
| 535 | + }) | ||
| 536 | + .classed('after', function (d, i) { | ||
| 537 | + return i > self.eBusStopData.currentStopStationIndex | ||
| 538 | + }) | ||
| 539 | + .style('fill', function (d, i) { | ||
| 540 | + if (i === self.eBusStopData.currentStopStationIndex) { | ||
| 541 | + return self.chart_up_line_circle_f_color_current | ||
| 542 | + } else if (i < self.eBusStopData.currentStopStationIndex) { | ||
| 543 | + return self.chart_up_line_circle_f_color_before | ||
| 544 | + } else { | ||
| 545 | + return self.chart_up_line_circle_f_color_after | ||
| 546 | + } | ||
| 547 | + }) | ||
| 548 | + .style('stroke-width', 0) // 暂时外部的stroke设置为0,不参与属性设置 | ||
| 549 | + .attr('r', self.chart_up_line_circle_r) // css也设置了,但是有些游览器不支持(如 android5.1的内置游览器),所以直接定义成属性 | ||
| 550 | + .attr('cx', function (d, i) { | ||
| 551 | + return xScale(i) | ||
| 552 | + }) | ||
| 553 | + .attr('cy', function () { | ||
| 554 | + return chartTopPadding | ||
| 555 | + }) | ||
| 556 | + .attr('data-id', function (d) { | ||
| 557 | + return d.code | ||
| 558 | + }) | ||
| 559 | + itemsUpdate.select('circle') | ||
| 560 | + .attr('cx', function (d, i) { | ||
| 561 | + return xScale(i) | ||
| 562 | + }) | ||
| 563 | + .attr('cy', function () { | ||
| 564 | + return chartTopPadding | ||
| 565 | + }) | ||
| 566 | + | ||
| 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 | ||
| 573 | + }) | ||
| 574 | + .classed('before', function (d, i) { | ||
| 575 | + return i < self.eBusStopData.currentStopStationIndex | ||
| 576 | + }) | ||
| 577 | + .classed('after', function (d, i) { | ||
| 578 | + return i > self.eBusStopData.currentStopStationIndex | ||
| 579 | + }) | ||
| 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 | + } | ||
| 588 | + }) | ||
| 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 | + } | ||
| 597 | + }) | ||
| 598 | + .attr('textLength', self.chart_station_text_length) | ||
| 599 | + .text(function (d) { | ||
| 600 | + if (!d.name) { | ||
| 601 | + return 0 | ||
| 602 | + } | ||
| 603 | + return d.name | ||
| 604 | + }) | ||
| 605 | + .attr('title', function (d) { | ||
| 606 | + return d.name | ||
| 607 | + }) | ||
| 608 | + .attr('x', function (d, i) { | ||
| 609 | + return xScale(i) | ||
| 610 | + }) | ||
| 611 | + .attr('y', function (d) { | ||
| 612 | + return chartStopNameTopPadding | ||
| 613 | + }) | ||
| 614 | + itemsUpdate.select('text.station_text') | ||
| 615 | + .classed('up', true) | ||
| 616 | + .text(function (d) { | ||
| 617 | + if (!d.name) { | ||
| 618 | + return 0 | ||
| 619 | + } | ||
| 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 | + }) | ||
| 628 | + .attr('y', function (d) { | ||
| 629 | + return chartStopNameTopPadding | ||
| 630 | + }) | ||
| 631 | + } | ||
| 632 | + } | ||
| 633 | +} |
front-end/h5/src/components/core/plugins/index.js
| @@ -33,6 +33,8 @@ import EBusStopLineChartList from 'core/plugins/bsth/lggj/list/eBusStop-line-cha | @@ -33,6 +33,8 @@ import EBusStopLineChartList from 'core/plugins/bsth/lggj/list/eBusStop-line-cha | ||
| 33 | import MhgjEBusStopLineChart from 'core/plugins/bsth/mhgj/chart/mhgj-eBusStop-line-chart' | 33 | import MhgjEBusStopLineChart from 'core/plugins/bsth/mhgj/chart/mhgj-eBusStop-line-chart' |
| 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' | ||
| 37 | + | ||
| 36 | export const pluginsList = [ | 38 | export const pluginsList = [ |
| 37 | // { | 39 | // { |
| 38 | // i18nTitle: { | 40 | // i18nTitle: { |
| @@ -351,7 +353,7 @@ export const pluginsList = [ | @@ -351,7 +353,7 @@ export const pluginsList = [ | ||
| 351 | title: '电子站牌单线路模拟图2', | 353 | title: '电子站牌单线路模拟图2', |
| 352 | icon: 'list', | 354 | icon: 'list', |
| 353 | component: MhgjEBusStopLineChart, | 355 | component: MhgjEBusStopLineChart, |
| 354 | - visible: true, | 356 | + visible: false, |
| 355 | name: MhgjEBusStopLineChart.name | 357 | name: MhgjEBusStopLineChart.name |
| 356 | }, | 358 | }, |
| 357 | 359 | ||
| @@ -367,6 +369,19 @@ export const pluginsList = [ | @@ -367,6 +369,19 @@ export const pluginsList = [ | ||
| 367 | name: MhgjEBusStopLineChartList.name | 369 | name: MhgjEBusStopLineChartList.name |
| 368 | }, | 370 | }, |
| 369 | 371 | ||
| 372 | + { | ||
| 373 | + i18nTitle: { | ||
| 374 | + 'en-US': 'OthergjEBusStopLineChart', | ||
| 375 | + 'zh-CN': '电子站牌单线路模拟图3' | ||
| 376 | + }, | ||
| 377 | + title: '电子站牌单线路模拟图3', | ||
| 378 | + icon: 'list', | ||
| 379 | + component: OthergjEBusStopLineChart, | ||
| 380 | + visible: true, | ||
| 381 | + name: OthergjEBusStopLineChart.name | ||
| 382 | + }, | ||
| 383 | + | ||
| 384 | + | ||
| 370 | // { | 385 | // { |
| 371 | // i18nTitle: { | 386 | // i18nTitle: { |
| 372 | // 'en-US': 'LineChart', | 387 | // 'en-US': 'LineChart', |