可视化系列——dataV,Echarts,蚂蚁金服L7世界地图引入,数字翻牌器,全屏,自定义排名轮播表

970 阅读3分钟

​​​​​​​本文已参与「新人创作礼」活动,一起开启掘金创作之路。

目录

L7相关概念 

构造函数Scene

PointLayer 

基本用法

shape 类型 

style 

tips

地图事件

Popup信息框

option

方法:setLnglat

方法:setDOMContent

全屏效果实现 

数字翻牌器效果实现


和以往的项目进行对比,添加了一些新的东西,这里总结一下(后续更新):

使用到的技术栈
vue-cli3
vue-router
 Apache ECharts
 DataV
 [蚂蚁地理空间数据可视化L7](l7.antv.vision/zh "蚂蚁地理空间数据可视化L7")
使用json模拟数据结构

引入dataV

npm install @jiaminghi/data-view 

main.js中需要引入以下安装包

import router from "./router";
import dataV from "@jiaminghi/data-view";
import "./plugins/wyz-echarts/wyz-echarts.js";
Vue.use(dataV);

用L7里面的东西可以通过页面进行局部引入

import { Scene, PointLayer, Popup } from "@antv/l7";
import { GaodeMap } from "@antv/l7-maps";

引入地图L7地图:

首先需要一个容器来包裹这个全屏的大地图

<div id="userMap"></div>

安装L7(里面包含了地图)

npm install --save @antv/l7 

L7相关概念 

构造函数Scene

      const scene = new Scene({
        id: "userMap", // 需传入 dom 容器或者容器 id
        logoVisible:false, // 关闭L7的logo
        map: new GaodeMap({
          pitch: 0,// pitch 地图倾角
          style: "dark", //地图样式,L7内置了三种主体默认样式,dark,light,normal
          mapStyle: "amap://styles/darkblue",
          center: [113.631419, 34.753439], // center 地图中心
          zoom: 5, // 地图初始显示级别 {number} Mapbox (0-24) 高德 (2-19)
          token: "ced0d726cd96553ba8b5b3521671aaf4",
        }),
      });

打印构造函数的结构 ,如下图所示:


PointLayer 

点数据的展示,根据经纬点绘制图形,数据源支持 JSON、GeoJSON、CSV 三种数据格式。

基本用法

const pointLayer = new PointLayer({ zIndex: 1 })    // zIndex的作用:图层绘制顺序,数值大绘制在上层,可以控制图层绘制的上下层级
          .source(cityData.data.cityList, {
            parser: {
              type: "json",
              x: "longitude", //lng
              y: "latitude", //lat
            },
          })
          .shape("square") //shape 类型 //'simple', 'circle', 'square', 'hexagon', 'triangle''pentagon',  'octogon', 'hexagram','rhombus',  'vesica',
          .animate(true)
          .size("count", [0, 45]) // 使用字段映射到大小,并指定最大值和最小值
          .color("count", ["#3CA0FF", "#3CA0FF", "#3CA0FF"]) //将数据值映射到图形的颜色上的方法。
          .active(true)
          .style({
            opacity: 0.5, //opacity 设置透明度 大部分图层都支持
            /* stroke 线填充颜色 仅点图层支持 */
            strokeWidth: 0, //strokeWidth 线的宽度 仅点图层支持
          });

shape 类型 

'simple', 'circle', 'square', 'hexagon',
 'triangle',  'pentagon',  'octogon', 
'hexagram','rhombus',  'vesica'

style 

 类似于这种效果

城市气泡:(使用canvas划出气泡)

    // 用户城市气泡
    initUserPopover(arrList) {
      let canvas = document.getElementById("cityPopover");
      let ctx = canvas.getContext("2d");
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      //填充画布
      ctx.lineWidth = 8;
      let beginDeg = Math.PI * 1.5;
      let endDeg = Math.PI * 1.5;
      arrList.forEach((t, index) => {
        t.percentageData.forEach((l) => {
          endDeg = beginDeg + 2 * Math.PI * l.value;
          ctx.beginPath();
          ctx.strokeStyle = l.color;
          ctx.arc(60, 60, t.radius, beginDeg, endDeg, false);
          ctx.stroke();
          beginDeg = endDeg;
          ctx.closePath();

          ctx.moveTo(0, 0); //移动笔触到原点
          ctx.fillStyle = "white"; //文本颜色
          ctx.font = "12px normal ";
          ctx.textAlign = "right";
          ctx.fillText(`${(t.value * 100).toFixed(1)}%`, 55, (index + 1) * 16);
        });
      });
    },

 效果如下:

tips:(这里是一个样式,可以直接通过.tips修改器样式)


地图事件

scene.on('loaded', () => {}); //地图加载完成触发
scene.on('mapmove', () => {}); // 地图平移时触发事件
scene.on('movestart', () => {}); // 地图平移开始时触发
scene.on('moveend', () => {}); // 地图移动结束后触发,包括平移,以及中心点变化的缩放。如地图有拖拽缓动效果,则在缓动结束后触发
scene.on('zoomchange', () => {}); // 地图缩放级别更改后触发
scene.on('zoomstart', () => {}); // 缩放开始时触发
scene.on('zoomend', () => {}); // 缩放停止时触发

Popup信息框

地图标注信息窗口,用于展示地图要素的属性信息

option

  • closeButton 是否显示关闭按钮,布尔值,默认为 true。
  • closeButtonOffsets 显示关闭按钮时生效,[number, number],默认为 [0, 0],以右上角为起始点。
  • closeOnClick 是否在点击地图的时候关闭弹框,布尔值,默认为 true
  • maxWidth 弹框最宽值,默认为 240px
  • anchor 弹框锚点,默认值为 bottom,可选值有 center、top、top-left、left、bottom-left、bottom、bottom-right、right、top-right
  • offsets    Array  偏移量  [ 0, 0 ] 分别表示 X, Y 的偏移量

方法:setLnglat

设置 popup 的经纬度位置

支持数组

[112, 32];

经纬度对象

const lnglat = {
  lng: 112.323,
  lat: 30.456,
};

popup.setLnglat([112, 32]);

 方法:setDOMContent

  • 参数 htmlNode dom 对象 区别于 setHtml 对象只能传字符串

全屏效果实现 

给图片设置点击事件

<img class="full-img" @click="showFullScreen" src="@/assets/fullscreen.png" alt="" />

    // 全屏
    showFullScreen () {
      let element = document.documentElement
      if (this.fullscreen) {
        if (document.exitFullscreen) {
          document.exitFullscreen()
        } else if (document.webkitCancelFullScreen) {
          document.webkitCancelFullScreen()
        } else if (document.mozCancelFullScreen) {
          document.mozCancelFullScreen()
        } else if (document.msExitFullscreen) {
          document.msExitFullscreen()
        }
      } else {
        if (element.requestFullscreen) {
          element.requestFullscreen()
        } else if (element.webkitRequestFullScreen) {
          element.webkitRequestFullScreen()
        } else if (element.mozRequestFullScreen) {
          element.mozRequestFullScreen()
        } else if (element.msRequestFullscreen) {
          // IE11
          element.msRequestFullscreen()
        }
      }
      this.fullscreen = !this.fullscreen
    },

 数字翻牌器效果实现

<span :class="[{'flop-figure': !isNaN(ls)}, {'flop-comma': isNaN(ls)}]" v-for="(ls, index) in item.valueArr" :key="item.id + index">
   <i v-if="!isNaN(ls)">0123456789</i>
   <span v-else>{{ls}}</span>
</span>

  // 数字翻牌器效果
  .flop-figure {
    position: relative;
    display: flex;
    font-size: 36px;
    width: 23px;
    height: 100%;
    color: #4a90e2;
    line-height: 23px;
    overflow: hidden;
    writing-mode: vertical-lr;
    text-orientation: upright;
    i {
      position: absolute;
      font-style: normal;
      transition: transform 0.6s ease-in-out;
      letter-spacing: 10px;
    }
  }

 this.timedRefresh(this.cityInfoList, "city"); //重复刷新数字翻牌器
    // 设置文字滚动
    setNumberTransform(item) {
      const numberItems = document.querySelectorAll(`.${item.id}  i`);
      // const numberItems = this.$refs[`${item.id}`]
      const numberArr = item.valueArr.filter((item) => !isNaN(item));
      numberItems.forEach((t) => {
        t.style.transition = "transform 0s ease-in-out";
        t.style.transform = `translateY(-0%)`;
      });
      setTimeout(() => {
        numberItems.forEach((ls, index) => {
          ls.style.transition = "transform 0.8s ease-in-out";
          ls.style.transform = `translateY(-${numberArr[index] * 10}%)`;
        });
      }, 15);
    },
    // 刷新数字翻牌器
    timedRefresh(targetList, type) {
      let cityTimer;
      let userTimer;
      let deviceTimer;
      if (type === "city") {
        cityTimer = this.initInterval(targetList, 1000);
      } 
      this.$once("hook:beforeDestroy", () => {
        clearInterval(cityTimer);
        clearInterval(userTimer);
        clearInterval(deviceTimer);
        userTimer = null;
        cityTimer = null;
        deviceTimer = null;
      });
    },
    // 定时
    initInterval (targetList, time) {
      const { setNumberTransform } = this
      return setInterval((function fn(){
        targetList.forEach(t => {
          setTimeout(() => {
            setNumberTransform(t)
          }, 50)
        })
        return fn
      })(), time)
    },

因为受全屏影响,这里要在mounted生命周期中来删除监听到的高度

  mounted() {    
    this.setElementHeight()
    // 调整浏览器窗口大小时执行
    window.addEventListener('resize', this.setElementHeight)
    this.$once('hook:beforeDestroy', () => {
      window.removeEventListener('resize', this.setElementHeight)
    })
    this.initUserMap();
}

    // 设置DOM高度
    setElementHeight () {
     clearTimeout(this.timer)
      this.timer = setTimeout(() => {
        this.showLoading()
        this.height = `${(this.$refs.sectionRef.offsetHeight - 30) / 3}px`
        console.log(this.height);
      }, 100)
    },

效果如下:

\