关于cesium根据地形画区域面积并覆盖在3d表面上

最近一直在研究在3d地图上添加区域还有车辆路径路线,很是秃然啊!在不断的百度百度再百度,终于有了一套解决办法,先演示一下操作过程,

drawLine()方法

 drawPlane()方法

下面就来堆代码吧。

一、viewer.scene.pickPosition与viewer.camera.pickEllipsoid的区别

前提是开启了地形检测viewer.scene.globe.depthTestAgainstTerrain = true;一般开启会占用一定内存,但是获取笛卡尔坐标更精确了,否则用viewer.camera.pickEllipsoid的话,可能画线的鼠标位置跟线的实际位置差距很大

二、获取鼠标点击位置的笛卡尔坐标

在画区域面积的时候坐标是必备的,通常获取坐标的方法有两中viewer.scene.pickPosition()与viewer.camera.pickEllipsoid(),这就不得不说说两者的区别了

开启了地形检测的话viewer.scene.pickPosition()获取坐标要比viewer.camera.pickEllipsoid()更精确,(viewer.scene.globe.depthTestAgainstTerrain = true),直接用viewer.camera.pickEllipsoid的话,可能画线的鼠标位置跟线的实际位置差距很大,这里推荐使用开启地形检测的pickPosition()方法

//首先建立ScreenSpaceEventHandler对象获取鼠标左击事件
this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
this.handler.setInputAction((movement) => {
      let cartesian = this.viewer.scene.pickPosition(movement.position);
      let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
      let lng = Cesium.Math.toDegrees(cartographic.longitude);
      let lat = Cesium.Math.toDegrees(cartographic.latitude);
      let hei = Cesium.Math.toDegrees(cartographic.height);
 }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

以上是获取鼠标左击的迪卡尔坐标并且转换成经纬度坐标

三、根据多点坐标画点或面

两点一线,三点/多点一面,要画线/面必须要2个或多个坐标才能绘画,光有一个坐标是不够的,所以我们要先命名一个变量let positions = [],来记录点击点的坐标,然后根据后面的转换变为画线和面积的坐标,同时需要命名一个变量来存储层次结构的对象  polygon = new Cesium.PolygonHierarchy(),还需要一个codeInfo来记录移动点的所有数据

1.下面就可以通过绑定鼠标事件来获取初始位置

this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
    // left
    this.handler.setInputAction((movement) => {
      let cartesian = this.viewer.scene.pickPosition(movement.position);
      let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
      let lng = Cesium.Math.toDegrees(cartographic.longitude);
      let lat = Cesium.Math.toDegrees(cartographic.latitude);
      let hei = Cesium.Math.toDegrees(cartographic.height);

      // console.log("><><><><><>", cartographic);
      if (cartesian && cartesian.x) {
        if (positions.length == 0) {
          positions.push(cartesian.clone());
        }
        codeInfo.push([lng, lat, hei]);
        positions.push(cartesian.clone());

        polygon.positions.push(cartesian.clone());
      }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

2.绑定鼠标移动来获取移动位置

this.handler.setInputAction((movement) => {
      let cartesian = this.viewer.scene.pickPosition(movement.endPosition);
      let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
      let lng = Cesium.Math.toDegrees(cartographic.longitude);
      let lat = Cesium.Math.toDegrees(cartographic.latitude);
      let hei = Cesium.Math.toDegrees(cartographic.height);

      if (positions.length >= 0) {
        if (cartesian && cartesian.x) {
          positions.pop();
          positions.push(cartesian);
          polygon.positions.pop();
          polygon.positions.push(cartesian);
          codeInfo.pop();
          codeInfo.push([lng, lat, hei]);
        }
      }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

3.绑定鼠标右键来获取终点位置

 this.handler.setInputAction(() => {
      this.infoDetail.planeSelf.push({ id: id, positions: codeInfo, polygon });
      console.log("planeSelf", this.infoDetail.planeSelf);
      this.handler.destroy();
      positions.push(positions[0]);
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);

这样的话就获取了所有点坐标的信息,接下来就画线/面了。

4.绘画

我们通过添加实体的方法来绘制线/面

 polyObj = this.viewer.entities.add({
            id: id,
            name: "planeSelf",
            polyline: {
              positions: new Cesium.CallbackProperty(function () {
                return positions;
              }, false),
              width: this.config.borderWidth,
              material: this.config.borderColor,
              clampToGround: true,
            },
            polygon: {
              hierarchy: new Cesium.CallbackProperty(function () {
                return polygon;
              }, false),
              material: this.config.material,
              clampToGround: true,
            },
          });
        }

这样我们就可以根据我们的鼠标来绘制我们的线/面了

四、根据记录的点实现线/面的绘制

我们根据codeInfo记录的数据获取了线/面的点坐标数据,只需在绘制方法中为其添加坐标参数,即可实现线/面的绘制

  addLine(id, name, positions) {
    this.viewer.entities.add({
      name: name,
      id: id,
      polyline: {
        positions: new Cesium.CallbackProperty(function () {
          return positions;
        }, false),
        width: this.config.borderWidth,
        material: this.config.borderColor,
        clampToGround: true,
      },
    });
  }

五、完整绘制线/面的类方法

import * as Cesium from "cesium";

// add...方法的position数据从this.infoDetail中获取

export class Draw {
  constructor(viewer, config) {
    /**cesium实例对象 */
    this.viewer = viewer;
    /**绘制要素的相关配置
       * 默认配置
       * {
          borderColor: Cesium.Color.BLUE,  边框颜色
          borderWidth: 2, 边框宽度
          material: Cesium.Color.GREEN.withAlpha(0.5),填充材质
      }
      */
    this.config = config || {
      borderColor: Cesium.Color.BLUE,
      borderWidth: 2,
      material: Cesium.Color.GREEN.withAlpha(0.5),
    };
    /**存贮绘制的数据 坐标 */
    this.infoDetail = {
      point: [],
      line: [],
      rectangle: [],
      circle: [],
      planeSelf: [],
    };
    this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
  }

  /*******
   * @param:  id 必须是唯一的 name、position是三点的笛卡尔坐标[lng,lat,hei]
   * @function: function
   * @return {*}
   * @description: 绘制方法
   */
  addPoint(id, name, position) {
    this.viewer.entities.add({
      position: Cesium.Cartesian3.fromDegrees(...position),
      name: name,
      id: id,
      point: {
        color: this.config.material,
        pixelSize: 12,
        outlineColor: this.config.borderColor,
        outlineWidth: this.config.borderWidth,
      },
    });
  }
  /*******
   * @param:  id 必须是唯一的 name、positions
   * @function: function
   * @return {*}
   * @description: 绘制方法
   */
  addLine(id, name, positions) {
    this.viewer.entities.add({
      name: name,
      id: id,
      polyline: {
        positions: new Cesium.CallbackProperty(function() {
          return positions;
        }, false),
        width: this.config.borderWidth,
        material: this.config.borderColor,
        clampToGround: true,
      },
    });
  }
  /*******
   * @param:  id 必须是唯一的 name、positions
   * @function: function
   * @return {*}
   * @description: 添加平面方法
   */
  addPlane(id, name, positions) {
    let polygon = new Cesium.PolygonHierarchy();
    polygon.positions = positions;
    this.viewer.entities.add({
      id: id,
      name: name,
      polyline: {
        positions: new Cesium.CallbackProperty(function() {
          return positions;
        }, false),
        width: this.config.borderWidth,
        material: this.config.borderColor,
        clampToGround: true,
      },
      polygon: {
        hierarchy: new Cesium.CallbackProperty(function() {
          return polygon;
        }, false),
        material: this.config.material,
        clampToGround: true,
      },
    });
  }
  drawPoint() {
    this.handler.destroy();

    this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
    this.handler.setInputAction((click) => {
      let position = this.getMovement(click).position;
      /**实体的唯一标注 */
      let id = new Date().getTime();

      this.addPoint(id, "point", position);

      this.infoDetail.point.push({ id, position });
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

    this.handler.setInputAction((click) => {
      this.handler.destroy();
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  }

  /*******
   * @function: function
   * @description: 绘制矩形区域
   * @return {*}
   * @author: xk
   */
  drawRectangle() {
    this.handler.destroy();
    /**
     * 矩形四点坐标
     */
    let westSouthEastNorth = [];
    /**实体的唯一标注 */
    let id = null;
    /**地图点击对象 */
    this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
    this.handler.setInputAction((click) => {
      /**点击位置笛卡尔坐标 */
      let cartesian = this.viewer.scene.pickPosition(click.position);
      /**笛卡尔转弧度坐标 */
      let cartographic = Cesium.Cartographic.fromCartesian(cartesian, false);
      /**点击位置经度 */
      let lng1 = Cesium.Math.toDegrees(cartographic.longitude);
      /**点击位置维度 */
      let lat1 = Cesium.Math.toDegrees(cartographic.latitude);
      /**边框坐标 */
      westSouthEastNorth = [lng1, lat1];
      id = new Date().getTime();
      if (westSouthEastNorth) {
        this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
      }
      /**面实例对象 */
      let polygons = this.viewer.entities.add({
        name: "rectangle",
        id: id,
        polygon: {
          hierarchy: new Cesium.CallbackProperty(function() {
            return {
              positions: Cesium.Cartesian3.fromDegreesArray(westSouthEastNorth),
            };
          }),
          height: 0,
          // 填充的颜色,withAlpha透明度
          material: this.config.material,
          // 是否被提供的材质填充
          fill: true,
          // 是否显示
          show: true,
        },
        polyline: {
          positions: new Cesium.CallbackProperty(function() {
            return Cesium.Cartesian3.fromDegreesArray(westSouthEastNorth);
          }),
          material: this.config.borderColor,
          width: this.config.borderWidth,
          zIndex: 1,
        },
      });
      this.handler.setInputAction((move) => {
        let cartesian = this.viewer.scene.pickPosition(move.endPosition);
        let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
        let lng = Cesium.Math.toDegrees(cartographic.longitude);
        let lat = Cesium.Math.toDegrees(cartographic.latitude);

        westSouthEastNorth = [
          lng1,
          lat1,
          lng1,
          lat,
          lng,
          lat,
          lng,
          lat1,
          lng1,
          lat1,
        ];
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

    this.handler.setInputAction(() => {
      this.handler.destroy();
      this.infoDetail.rectangle.push({ id: id, position: westSouthEastNorth });
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  }
  /*******
   * @function: function
   * @description: 绘制圆形区域
   * @return {*}
   * @author: xk
   */
  drawCircle() {
    this.handler.destroy();
    /**实体的唯一标注 */
    let id = null;

    /**圆半径 */
    let radius = 0;
    /**圆心 */
    let lngLat = [];
    /**鼠标事件 */
    this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
    this.handler.setInputAction((click) => {
      id = new Date().getTime();
      let cartesian = this.viewer.scene.pickPosition(click.position);

      // console.log(">>>", click.position);
      let cartographic = Cesium.Cartographic.fromCartesian(cartesian);

      // console.log(">>>>>>>>>", cartographic);
      let lng = Cesium.Math.toDegrees(cartographic.longitude);
      let lat = Cesium.Math.toDegrees(cartographic.latitude);
      let hei = Cesium.Math.toDegrees(cartographic.height);
      lngLat = [lng, lat, hei];
      let entity = this.viewer.entities.add({
        position: new Cesium.CallbackProperty(function() {
          return new Cesium.Cartesian3.fromDegrees(...lngLat);
        }, false),
        name: "circle",
        id: id,
        ellipse: {
          height: hei / 57.3,
          outline: true,
          material: this.config.material,
          outlineColor: this.config.borderColor,
          outlineWidth: this.config.borderWidth,
        },
        // label: {
        //   text: "区域一",
        //   font: "18px sans-serif",
        //   fillColor: Cesium.Color.GOLD,
        //   style: Cesium.LabelStyle.FILL_AND_OUTLINE,
        //   outlineWidth: 2,
        //   verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
        //   pixelOffset: new Cesium.Cartesian2(0, 0),
        //   // 对齐方式(水平和竖直)
        //   horizontalOrigin: Cesium.HorizontalOrigin.LEFT,

        //   showBackground: true,
        //   backgroundColor: new Cesium.Color.fromBytes(0, 0, 0),
        //   show: true,
        // },
      });
      entity.ellipse.semiMajorAxis = new Cesium.CallbackProperty(function() {
        return radius;
      }, false);
      entity.ellipse.semiMinorAxis = new Cesium.CallbackProperty(function() {
        return radius;
      }, false);

      if (lngLat) {
        this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
      }
      this.handler.setInputAction((move) => {
        let cartesian2 = this.viewer.scene.pickPosition(move.endPosition);
        radius = Cesium.Cartesian3.distance(cartesian, cartesian2);
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

    this.handler.setInputAction(() => {
      this.infoDetail.circle.push({ id: id, center: lngLat, radius: radius });
      this.handler.destroy();
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  }
  /*******
   * @function: function
   * @description: 自定义区域绘制
   * @return {*}
   * @author: xk
   */
  drawPlane() {
    this.handler.destroy();
    /**实体的唯一标注 */
    let id = new Date().getTime();
    /**记录拐点坐标 */
    let positions = [],
      /**记录返回结果 */
      codeInfo = [],
      /**面的hierarchy属性 */
      polygon = new Cesium.PolygonHierarchy(),
      /**面对象配置 */
      polyObj = null;
    this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
    // left
    this.handler.setInputAction((movement) => {
      let cartesian = this.viewer.scene.pickPosition(movement.position);
      let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
      let lng = Cesium.Math.toDegrees(cartographic.longitude);
      let lat = Cesium.Math.toDegrees(cartographic.latitude);
      let hei = Cesium.Math.toDegrees(cartographic.height);

      // console.log("><><><><><>", cartographic);
      if (cartesian && cartesian.x) {
        if (positions.length == 0) {
          positions.push(cartesian.clone());
        }
        codeInfo.push([lng, lat, hei]);
        positions.push(cartesian.clone());

        polygon.positions.push(cartesian.clone());

        if (!polyObj) {
          polyObj = this.viewer.entities.add({
            id: id,
            name: "planeSelf",
            polyline: {
              positions: new Cesium.CallbackProperty(function() {
                return positions;
              }, false),
              width: this.config.borderWidth,
              material: this.config.borderColor,
              clampToGround: true,
            },
            polygon: {
              hierarchy: new Cesium.CallbackProperty(function() {
                return polygon;
              }, false),
              material: this.config.material,
              clampToGround: true,
            },
          });
        }
      }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    // mouse
    this.handler.setInputAction((movement) => {
      let cartesian = this.viewer.scene.pickPosition(movement.endPosition);
      let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
      let lng = Cesium.Math.toDegrees(cartographic.longitude);
      let lat = Cesium.Math.toDegrees(cartographic.latitude);
      let hei = Cesium.Math.toDegrees(cartographic.height);

      if (positions.length >= 0) {
        if (cartesian && cartesian.x) {
          positions.pop();
          positions.push(cartesian);
          polygon.positions.pop();
          polygon.positions.push(cartesian);
          codeInfo.pop();
          codeInfo.push([lng, lat, hei]);
        }
      }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

    // right
    this.handler.setInputAction((movement) => {
      this.infoDetail.planeSelf.push({ id: id, positions: codeInfo, polygon });
      console.log("planeSelf", this.infoDetail.planeSelf);
      this.handler.destroy();
      positions.push(positions[0]);
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  }

  /*******
   * @function: function
   * @return {*}
   * @author: xk
   * @description: 绘制线段
   */
  drawLine() {
    this.handler.destroy();
    /**实体的唯一标注 */
    let id = null;
    /**记录拐点坐标 */
    let positions = [],
      /**记录返回结果 */
      codeInfo = [],
      /**面的hierarchy属性 */
      polygon = new Cesium.PolygonHierarchy(),
      /**面对象配置 */
      polyObj = null;
    this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
    // left
    this.handler.setInputAction((movement) => {
      id = new Date().getTime();
      let cartesian = this.getMovement(movement).cartesian;
      let position = this.getMovement(movement).position;

      if (cartesian && cartesian.x) {
        if (positions.length == 0) {
          positions.push(cartesian.clone());
        }
        codeInfo.push(position);
        positions.push(cartesian.clone());
        polygon.positions.push(cartesian.clone());
        if (!polyObj) {
          polyObj = this.addLine(id, "line", positions);
        }
      }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    // mouse
    this.handler.setInputAction((movement) => {
      let cartesian = this.viewer.scene.pickPosition(movement.endPosition);
      let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
      let lng = Cesium.Math.toDegrees(cartographic.longitude);
      let lat = Cesium.Math.toDegrees(cartographic.latitude);

      if (positions.length >= 0) {
        if (cartesian && cartesian.x) {
          positions.pop();
          positions.push(cartesian);
          codeInfo.pop();
          codeInfo.push([lng, lat]);
        }
      }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

    // right
    this.handler.setInputAction((movement) => {
      this.infoDetail.line.push({ id, positions: codeInfo });
      console.log("infoDetail", this.infoDetail.line);
      this.handler.destroy();
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  }
  /*******
   * @function: function
   * @description: 移除实体对象
   * @return {*}
   * @author: xk
   */
  removeEntity() {
    this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
    this.handler.setInputAction((move) => {
      /**实体对象信息  {id:entities,primitive:。。} */
      let pick = this.viewer.scene.pick(move.endPosition);

      if (pick && pick.id && pick.id.id) {
        document.body.style.cursor = "pointer";
        this.handler.setInputAction((click) => {
          let newPoint;
          switch (pick.id.name) {
            case "point":
              /**删除某一条数据 */
              newPoint = this.infoDetail.point.filter(
                (item) => item.id != pick.id._id
              );
              this.infoDetail.point = newPoint;
              break;
            case "line":
              /**删除某一条数据 */
              newPoint = this.infoDetail.line.filter(
                (item) => item.id != pick.id._id
              );
              this.infoDetail.line = newPoint;
              break;
            case "rectangle":
              /**删除某一条数据 */
              newPoint = this.infoDetail.rectangle.filter(
                (item) => item.id != pick.id._id
              );
              this.infoDetail.rectangle = newPoint;
              break;

            case "planeSelf":
              /**删除某一条数据 */
              newPoint = this.infoDetail.planeSelf.filter(
                (item) => item.id != pick.id._id
              );
              this.infoDetail.planeSelf = newPoint;
              break;
            case "circle":
              /**删除某一条数据 */
              newPoint = this.infoDetail.circle.filter(
                (item) => item.id != pick.id._id
              );
              this.infoDetail.circle = newPoint;
              break;
            default:
              break;
          }
          this.viewer.entities.remove(pick.id);
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
      } else {
        document.body.style = "cursor: default;";
      }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
  }
  /*******
   * @function: function
   * @return {*}
   * @author: xk
   * @description: 返回绘制数据
   */
  backInfoDetail() {
    return this.infoDetail;
  }
}

六、方法使用

//新建绘画对象
    let draw = new Draw(viewer, {
      borderColor: Cesium.Color.RED,
      material: Cesium.Color.BLUE.withAlpha(0.3),
    });
 draw.drawPlane();

绘画完后f12打开控制台会有这样的数据打印

红框中就是我们需要提取的position数据,通过addPlane方法就可以实现重绘了


    let polygon = [
      [
        {
          x: 337391.70993699186,
          y: -4745401.190202851,
          z: 4234046.05863133,
        },
        {
          x: 338566.5104026345,
          y: -4745705.230711781,
          z: 4233614.397144763,
        },
        {
          x: 337520.9493625825,
          y: -4746057.340173215,
          z: 4233305.240160256,
        },
        {
          x: 337387.1903192716,
          y: -4745398.61765625,
          z: 4234049.280300835,
        },
      ],
    ];

    draw.addPlane(123123, "planeSelf", polygon);

 教程到这里就结束了,喜欢的不要忘记关注点赞收藏哦

这里附上gitee仓库地址,可以直接拉取查看代码cesium-test: 用于cesium学习测试的仓库

这是我的qq:1711503830有什么问题欢迎添加讨论。

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Cesium是一种基于Web的地理信息系统框架,可以用来构建交互式的地球三维可视化应用程序。Cesium可以从不同的数据源中读取地理信息数据,并在地球上以三维模型的形式显示出来。同时,Cesium也提供了一些工具和功能,可以对地理信息数据进行分析和处理。 其中一项功能是根据地形生成TIN(Triangulated Irregular Network)三角网。TIN是一种将地形表面划分为不规则三角形的方法,通过连接地形上的点来形成网络。这种方法可以在保持地形曲线特征的同时,用较少的数据点来描述地形。 在Cesium中,用户可以将地形数据作为输入,通过调用相关的函数和方法,生成TIN三角网。地形数据可以是从数字高程模型(DEM)或其他数据源中获取的。然后,Cesium会将地形数据转换为一系列的点,然后使用Delaunay三角化算法将这些点连接成TIN三角网。Delaunay三角化算法是一种常用的将点集划分为三角形的方法,保证了生成的三角形具有良好的性质和几何约束。 生成TIN三角网后,Cesium可以将其以三维模型的形式显示在地球上。用户可以使用相机和交互控件来浏览和操作这个三维模型,观察地形的细节和特征。同时,用户也可以将其他地理信息数据与TIN三角网结合使用,进行进一步的分析和可视化。 总之,Cesium可以根据地形数据生成TIN三角网,帮助用户更好地理解和展示地形特征。它提供了简便的方法和功能,使得地理信息的可视化和分析变得更加直观和便捷。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值