deckGL自定义图层学习笔记

news2024/11/28 10:52:33

1.自定义图层

在这里插入图片描述

当使用DeckGL提供的图层还无法满足需求时(https://deck.gl/docs/api-reference/layers),可能就需要自定义图层了。在DeckGL中有常见的三种自定义图层的方式

  • 创建复合层(composite layers.)——复合层是一种可以创建其他层的特殊层
  • 子类层(Subclass a layer)——子类层是通过子类化其他层创建的新层。这允许开发人员重用现有层的所有接口和实现
  • 从0开始构建图层层——也就是使用WebGL自定义绘制图层绘制,这就意味着你可以完全控制图层生命周期,可以管理自己的模型并直接操作 WebGL 上下文,当然难度也是最大的…(感觉上面两个应用场景也不少了随着DeckGL的版本的升级提供了挺多常用的layer)

[1]图层的生命周期

为了理解每个 deck.gl Layer的子类都可以定义在其生命周期中的特定点调用的特定方法

  • initializeState - 对于刚刚添加的layer进行初始化时(初始化进发生一次),该[layer.updateState()](https://deck.gl/docs/api-reference/core/layer#updatestate)生命周期函数将会被调用
  • Updating-layer发生变化(如修改属性、数据等)时调用 layer.shouldUpdateState() 以确定图层是否需要更新。
    • 如果确实需要更新则在Layer渲染前调用 layer.updateState() ,通常在这一阶段通过调用[state.attributeManager.invalidate](https://deck.gl/docs/api-reference/core/attribute-manager#invalidate) 来重新计算attribute 和调用model.setUniforms来更新uniforms 变量/默认情况下,当 props.data 更改时,所有attribute都会失效并重新计算
  • Rendering - 渲染发生在每个渲染周期,将图层绘制到 WebGL 上下文。
    • 对于primitive layers, [layer.draw()](https://deck.gl/docs/api-reference/core/layer#draw)函数在此阶段将被调用
  • Picking - 当指针移过或单击 deck.gl 画布时发生
    • 拾取图层时,将调用 layer.getPickingInfo() 以生成有关已拾取内容的信息对象。然后将此对象传递给图层的 onHover 或 onClick 回调。
  • Finalization - 发生在每个被移除的层上,即来自上一个渲染周期的层,其 id 与当前周期中的任何层都不匹配。 layer.finalizeState() 在对该层的状态的引用被释放之前被调用

[2]复合层

复合层是一种特殊的图层,可以通过组合现有层来构建新的层(顾名思义:通过组合多个层来构成一个层)如GeoJsonLayer就是复合层

复合层中分为适配层Adaptor Layers和集合层Collection Layers

定义一个继承于CompositeLayer的layer

Adaptor Layers

使用复合“适配”层更改现有层的接口和行为通常很方便,而不是修改层本身(例如 S2Layer 是 PolygonLayer 之上的简单适配层)

简单的说也就是,根据现有层添加一些适配(如数据)

对于复合层主要的意义我估计就是使用相同的数据,来给原来的多个层使用渲染,然后组合为一个层

应用举例:

  • LASPointCloudLayer为Adaptor Layers的适配层
  • TopoJSONLayer为GeoJsonLayer的适配层
  • TextLayer, HexagonLayer, CPUGridLayer 等都为composite “adapter” layers.
Collection Layers

通常,一些复杂的可视化层是由使用一组具有通用属性的多个层合成的。例如:

  • 例如NodeLayer图层由ScatterplotLayer、TextLayer组合而成
  • GeoJsonLayer 、PolygonLayer 为集合层

创建一个集合层的优势:

  • 可以将处理特定数据格式或可视化配置的复杂代码收集到一个类中
  • 通过跨层共享相同的对象/缓冲区来提高内存使用率。复合层将管理数据源并将其向下传递给多个层,而不是每个子层加载和存储自己的原始数据副本。

例如:实现一个有icon和text的layer(通过组合IconLayer和TextLayer)

import {CompositeLayer, IconLayer, TextLayer} from 'deck.gl';

class LabeledIconLayer extends CompositeLayer {
   //一个组合图层需要实现renderLayers()方法并返回一个子图层数组
    renderLayers() {
        return [
          new IconLayer({
            //由于复合层不直接绘制到画布上,它通过设置其子层的props来控制渲染结果,而且子图层并不知道复合图层的,所以需要将复合图层的props映射到子图层相应的props
              id: `${this.props.id}-icon`,
              data: this.props.data,

              iconAtlas: this.props.iconAtlas,
              iconMapping: this.props.iconMapping,

              getPosition: this.props.getPosition,
              getIcon: this.props.getIcon,
              getSize: this.props.getIconSize,
              getColor: this.props.getIconColor
              //为了在需要重新计算访问器时使 updateTriggers 起作用
              updateTriggers: {
                  getPosition: this.props.updateTriggers.getPosition,
                  getIcon: this.props.updateTriggers.getIcon,
                  getSize: this.props.updateTriggers.getIconSize,
                  getColor: this.props.updateTriggers.getIconColor
          	 }
          }),
          //由于复合层不直接绘制到画布上,它通过设置其子层的 props 来控制渲染结果
          new TextLayer({
            id: `${this.props.id}-label`,
            data: this.props.data,

            fontFamily: this.props.fontFamily,
            fontWeight: this.props.fontWeight,

            getPosition: this.props.getPosition,
            getText: this.props.getText,
            getSize: this.props.getTextSize
            getColor: this.props.getTextColor
            //为了在需要重新计算访问器时使 updateTriggers 起作用
            updateTriggers: {
              getPosition: this.props.updateTriggers.getPosition,
              getText: this.props.updateTriggers.getText,
              getSize: this.props.updateTriggers.getTextSize,
              getColor: this.props.updateTriggers.getTextColor
            }
          })
        ];
  	}
    
}
LabeledIconLayer.layerName = 'LabeledIconLayer';
//定义组合图层属性
LabeledIconLayer.defaultProps = {
  // Shared accessors
  getPosition: {type: 'accessor', value: x => x.position},
  // Icon properties
  iconAtlas: null,
  iconMapping: {type: 'object', value: {}, async: true},
  // Icon accessors
  getIcon: {type: 'accessor', value: x => x.icon},
  getIconSize: {type: 'accessor', value: 20},
  getIconColor: {type: 'accessor', value: [0, 0, 0, 255]},
  // Text properties
  fontFamily: DEFAULT_FONT_FAMILY,
  fontWeight: DEFAULT_FONT_WEIGHT,
  // Text accessors
  getText: {type: 'accessor', value: x => x.text},
  getTextSize: {type: 'accessor', value: 12}
  getTextColor: {type: 'accessor', value: [0, 0, 0, 255]}
}

子层 id 必须根据其父层的 id 动态生成,否则当有多个 LabeledIconLayers 实例时,它们的子层 id 将发生冲突。

例如还可以实现labeldGeoJsonLayer

小结

构建复合层的通用步骤为(和SubClass差不多)

  • 定义面向用户的api(继承你要使用的图层的defaultProps,然后自定义添加一些而外的props
    定义renderLayers()渲染逻辑,因为CompositeLayer并不是开箱即用的层,而是需要使用renderLayers()来组合其他层的渲染逻辑
  • 数据装换(通常想要渲染的数据和Layer要求的数据格式是不一样的),那么就可以需要使用CompositeLayer的数据解析逻辑“适配”你的数据格式,使用CompositeLayer的另外的好处是它允许多个子层共享同一个数据集,这就大程度的提升了数据传输性能。
    • 使用钩子函数updateState()来处理当数据发送变化时,在该函数下对数据进行处理,并会自动将处理结果存储在复合层的状态中。这样它也可以被子层访问。

例如根据geoJsonLayer定义一个CompositeLayer(给几何添加一些文本标注)

const {CompositeLayer, GeoJsonLayer, TextLayer} = deck;
//定义面向用户的prop API
const defaultProps = {
    //继承GeoJsonLayer props API
    ...GeoJsonLayer.defaultProps,
    //获取每个feature的label
    getLabel: {type: 'accessor', value: x => x.text},
    // 每个feature的label的大小
    getLabelSize: {type: 'accessor', value: 32},
    // 每个feature的label的颜色
    getLabelColor: {type: 'accessor', value: [0, 0, 0, 255]},
    // label始终面向相机
    billboard: true,
    // label大小单位
    labelSizeUnits: 'pixels',
    // Label background color
    labelBackground: {type: 'color', value: null, optional: true},
    // Label font
    fontFamily: 'Monaco, monospace'
}


class LabeledGeoJsonLayer extends CompositeLayer {
    //图层的生命周期函数,图层在初始化时被调用,对geojson数据做处理,提取取label文本数据
    updateState({changeFlags}) {
        const {data} = this.props;
        if (changeFlags.dataChanged && data) {
            const labelData = (data.features || data)
            .flatMap((feature, index) => {
                const labelAnchors = getLabelAnchors(feature);
                return labelAnchors.map(p => this.getSubLayerRow({position: p}, feature, index));
            });
            this.setState({labelData});
        }
    }
//渲染逻辑(使用同一个数据将GeoJsonLayer和TextLayer的渲染逻辑组合到一起)
    renderLayers() {
        const {
            getLabel,
            getLabelSize,
            getLabelColor,
            labelSizeUnits,
            labelBackground,
            billboard,
            fontFamily
        } = this.props;
        return [
            new GeoJsonLayer(this.props, this.getSubLayerProps({id: 'geojson'}), {
                data: this.props.data
            }),
            new TextLayer(this.getSubLayerProps({id: 'text'}), {
                data: this.state.labelData,
                billboard,
                sizeUnits: labelSizeUnits,
                backgroundColor: labelBackground,
                getPosition: d => d.position,
                getText: this.getSubLayerAccessor(getLabel),
                getSize: this.getSubLayerAccessor(getLabelSize),
                getColor: this.getSubLayerAccessor(getLabelColor)
            })
        ];
    }
}
LabeledGeoJsonLayer.layerName = 'LabeledGeoJsonLayer';
LabeledGeoJsonLayer.defaultProps = defaultProps;

const layer = new LabeledGeoJsonLayer({
    id: `countries-${Date.now()}`,
    data,
    filled: false,
    billboard: false,
    getLineColor: [180, 180, 180],
    getLabel: f => f.properties.name,
    getLabelSize: f => Math.pow(2, Math.log10(turf.area(f))) * 20,
    getLabelColor: [0, 64, 128],
    labelSizeUnits: 'meters',
    lineWidthMinPixels: 1
});

  deckgl.setProps({layers: [layer]});

[3]Subclassed Layers

deck.gl Layer被设计为易于扩展以添加功能。子类化允许重新定义层生命周期方法以及顶点和/或片段着色器。

扩展子类的示例:https://observablehq.com/d/ca5bcbd3d740693b

如果层中缺少一个小功能,子类化通常是添加它的好方法,常见的有:

通常写一个Subclassed Layers分为如下步骤:

  • 设计面向用户的API
    • To create a new layer class, just extend the Layer class from @deck.gl/core. By default, the layer does not do anything.
    • 用户通过传递prop给自定义的图层类的构造函数,用来告诉图层如何渲染给定的数据集,通常在defaultProps中扩展添加新的props给用户
    • 其实也就是是继承类后给静态成员等添加一些属性,用来在调用该类是根据数据添加一些option
  • 设定自定义attribute和uniform(定义数据怎么传的给的着色器变量的名字)
    https://observablehq.com/@pessimistress/deck-gl-tutorial-subclassing-a-layer
    • 可以通过定义attribute(每个对象特有)和uniform(所有对象共享)来使shader能够拿到拿到用户提供的数据
    • 默认情况下每个Layer都有一个AttributeManager来将要传递给attribute的数据上传到webgl缓冲区中(this.getAttributeManager())
    • 要自定义attribute的话,可以调用this.attributeManager.add()this.attributeManager.addInstanced(),然后将其添加到Layer的生命周期initializeState()
    • 设置自定义uniform则可以通过this.state.model.setUniforms()来设定
  • shader注入
    • deck.gl 的图层实现了标准的着色器hook,这样一来就可以在着色器中一些常见的地方添加shader代码了
Overriding Attribute Calculation

可以创建attribute变量,以供后面添加着色其代码时传输给着色其,在生命周期函数initializeState()中添加

export default class MultiColorPathLayer extends PathLayer {
	initializeState() {
        super.initializeState();
        this.getAttributeManager().addInstanced({
              instanceFrequency: {
              size: 1,
              accessor: 'getFrequency',
              defaultValue: 1
            },
        })
  	}
}
Overriding Shaders

着色器注入语句:

  • **vs:#decl:**向顶点着色器顶部(声明)注入代码
  • **vs:#main-start:**向顶点着色器主函数开始的地方注入代码
  • **vs:#main-end:**向顶点着色器主函数结束的地方注入代码
  • **vs:DeckGL_FILTER_SIZE:**顶点着色器中的一个函数,用于操纵几何体的大小,在投影计算前注入
    • DECKGL_FILTER_SIZE(inout vec3 size, VertexGeometry geometry)
  • **vs:DeckGL_FILTER_GL_POSITION:**向顶点着色器最终坐标计算上注入重写代码:顶点着色器中的一个函数,用于操作当前顶点的投影位置。投影后调用
    • DECKGL_FILTER_GL_POSITION(inout vec4 position, VertexGeometry geometry)
  • **vs:DeckGL_FILTER_COLOR:**向顶点着色器注入顶点颜色重写代码。
  • **fs:#decl:**向片元着色器注入声明代码。
  • **fs:#main-start:**向片元着色器主函数开始的地方注入代码。
  • **fs:#main-end:**向片元着色器主函数结束的地方注入代码。
  • **fs:DeckGL_FILTER_COLOR:**向片元着色器注入最终的颜色重写代码。
Defining Additional Uniforms

额外的Uniforms传递给自定义着色器的最佳方法是重写 draw() 方法:

Defining Additional Attributes
Layer Extensions

对于CompositeLayer通常采用添加图层扩展而不直接继承为子类图层去添加一个功能或效果,因为CompositeLayer通常是由几个图层组合而成的,所以在CompositeLayer继承进行添加自定义效果时,要确保在每个图层都生效就要通过对每个子图层进行子类扩展并添加相同的内容,这样就会比较麻且代码重复了,而图层扩展直接给CompositeLayer图层添加一个扩展变可以对其CompositeLayer的所有组成Layer都生效了。

有时我们需要对多个层进行子类化以添加类似的功能。层扩展是一种概括、重用和共享子类层代码的方法

[4]Primitive Layers

直接扩展Layer基类来自定义一个layer

[5]shader注入

着色器注入语句:

  • **vs:#decl****:**向顶点着色器顶部(声明)注入代码
  • **vs:#main-start****:**向顶点着色器主函数开始的地方注入代码
  • **vs:#main-end****:**向顶点着色器主函数结束的地方注入代码
  • **vs:DeckGL_FILTER_SIZE****:**顶点着色器中的一个函数,用于操纵几何体的大小,在投影计算前注入
    • DECKGL_FILTER_SIZE(inout vec3 size, VertexGeometry geometry)
  • **vs:DeckGL_FILTER_GL_POSITION****:**向顶点着色器最终坐标计算上注入重写代码:顶点着色器中的一个函数,用于操作当前顶点的投影位置。投影后调用
    • DECKGL_FILTER_GL_POSITION(inout vec4 position, VertexGeometry geometry)
  • **vs:DeckGL_FILTER_COLOR****:**向顶点着色器注入顶点颜色重写代码。
  • **fs:#decl****:**向片元着色器注入声明代码。
  • **fs:#main-start****:**向片元着色器主函数开始的地方注入代码。
  • **fs:#main-end****:**向片元着色器主函数结束的地方注入代码。
  • **fs:DeckGL_FILTER_COLOR****:**向片元着色器注入最终的颜色重写代码。

2.API使用

此部分为对官方文档的翻译

[1]Using Layers

  • 图层是deckGL中一个核心的概念, deck.gl 图层是一种打包的可视化类型,它采用一组数据,将每个数据与位置、颜色、拉伸等相关联,并将它们呈现在地图上。DeckGL定义了封装了很多图层,同时也允许通过编写着色其自定义图层
  • DeckGL将按顺序渲染渲染图层

[2]add Interactivity

  • 可以在实例化Deck实例时通过initialViewState配置相机位置

[3]坐标系统CS

把地理坐标中各种投影坐标系看做渲染引擎中的世界空间即可

基本概念
  • 世界空间(World space)

数据集的世界坐标系。它通常由数据源决定,例如生成数据的设备,以及存储在磁盘或云数据仓库中的格式

  • 公共空间(Common space)

为了将来自不同世界空间的数据正确地组合在一起,deck.gl 将它们转换为公共空间(Common space),一个统一的中间层 3D 空间,它是一个右手笛卡尔坐标系。一旦位置位于公共空间中,就可以安全地使用标准线性代数将它们添加、减去、旋转、缩放和拉伸为 3D 向量。这是 deck.gl 图层中所有几何处理的基础。

世界空间和公共空间之间的转换在 deck.gl 文档中称为“project”(世界空间到公共空间)和“unproject”(公共空间到世界空间),由世界空间规范(例如 WGS84)和投影方式(例如 Web Mercator)控制的过程。投影是作为 deck.gl 核心的一部分实现的

  • 屏幕空间

也就是像素坐标,对于给定的数据集,公共空间中的位置通常不会随着用户交互而改变,而它们在屏幕空间中的外观会随着用户平移、缩放和旋转相机而频繁变化

3.源码解读

其源码结构类似于常见的常见的地图引擎,很多继承类的关系。

MapboxLayer其实是对mapbox中的customLayer的进一步封装,实例化其实就是customLayer图层

[1]view

  • View 实例包装了相机的“硬配置”。一旦定义,就不需要经常更改
  • DeckGL允许调用多同时使用多个视图

[2]View State

  • View 实例必须与 viewState 对象结合使用
  • View State对象描述了 View 实例的状态。视图状态对象在运行时定义视图的临时属性,如相机位置、方向、缩放等。如果视图是交互式的,每次用户平移/旋转/缩放时,视图状态都会更新以反映改变

[3]Viewport

  • 视口实例是相机本身,是从 View 实例及其 viewState 中“解析”出来的。它处理数学运算,例如坐标投影/反投影、投影矩阵的计算以及着色器所需的其他 GLSL uniforms
  • 每当 viewState 更新时,view都会在后台创建一个新的viewport,通常,deck.gl 用户不需要直接使用视口Viewport。在某些用例中,Viewport 实例提供的 JavaScript 函数可以方便地投影和取消投影坐标。

坐标变换

在DeckGL绘制地理数据时因为地理数据的坐标系是很多种类的,所以在实际绘制时需要先对地理坐标进行转换,需要将经纬度为单位的地理进行投影为米为单位的,然后在进行类似于常见渲染引擎中的变换,如观测变换、投影变换等。

而因为地理数据的地理坐标的坐标系的种类是非常多的,所以为了方便计算和提升性能,大多数WebGIS引擎(如DeckGL、openlayers、mapbox)都默认只支持一种地理坐标系和一种投影坐标系,也就是WGS84 WKID=4326和web墨卡托 WKID=3857。

所以如果要使用其他坐标系的地理数据(如地方坐标系)时,就比较麻烦了,可以先查看有没有相应的API提供,如没有则自己写或者调用网络上其他开源的工具(如proj)来对坐标进行装换计算了。

Layer

Layer 类是所有 deck.gl Layers的基类,它对许多Layers提供了一些基础属性

MapboxLayer

在DeckGL中MapboxLayer类位于源码目录中的modules/mapbox/src/mapbox-layers.ts

//实现了MapBox的CustomLayerInterface接口
export default class MapboxLayer<LayerT extends Layer> implements CustomLayerInterface {
  id: string;
  type: 'custom';
  renderingMode: '2d' | '3d';
  map: Map | null;
  deck: Deck | null;
  props: MapboxLayerProps<LayerT>;

  constructor(props: MapboxLayerProps<LayerT>) {
    if (!props.id) {
      throw new Error('Layer must have an unique id');
    }

    this.id = props.id;
    this.type = 'custom';
    this.renderingMode = props.renderingMode || '3d';
    this.map = null;
    this.deck = null;
    this.props = props;
  }

  /* deck对onAdd方法的实现主要是创建deck实例,并添加设置一些props给deck实例,然后将 */
  onAdd(map: Map, gl: WebGLRenderingContext): void {
    获取mapbox的map实例,主要
    this.map = map;
    //这里通过Layer构建
    this.deck = getDeckInstance({map, gl, deck: this.props.deck});
    addLayer(this.deck, this);
  }

  onRemove(): void {
    if (this.deck) {
      removeLayer(this.deck, this);
    }
  }

  setProps(props: MapboxLayerProps<LayerT>) {
    // id cannot be changed
    Object.assign(this.props, props, {id: this.id});
    // safe guard in case setProps is called before onAdd
    if (this.deck) {
      updateLayer(this.deck, this);
    }
  }

  render() {
    drawLayer(this.deck!, this.map!, this);
  }
}

因为上面代码是基于Mapbox 代码为

下面以MVTLayer为里继续深入阅读源码,以了解其渲染机制:

安装说明

安装整个deckGL库

npm install deck.gl --save

选择性安装模块,直接安装DeckGL库的话其包含如下库

  • @deck.gl/core
  • Core module that handles the WebGL rendering pipeline, data management, and user interaction
    • @deck.gl/layers
  • Primitive layers that are the building blocks of all visualizations
    - @deck.gl/aggregation-layers - Advanced layers that aggregate data into alternative representations, e.g. heatmap, contour, hex bins, etc.
    - @deck.gl/geo-layers - Additional layers that handle geospatial use cases and GIS formats.
    - @deck.gl/mesh-layers - Additional layers that render 3D meshes and scene graphs.
    • @deck.gl/json - Declarative interface that supports specifying deck.gl layers and views using a JSON format.
    • @deck.gl/mapbox - An integration with the Mapbox custom layer API.
    • @deck.gl/react - React wrapper of deck.gl.
    • @deck.gl/test-utils - Testing utilities.

为了减小包的大小可以按需选择上面的包进行安装

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1069967.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ffmpeg从一个视频中提取音频

ffmpeg -i ~/video/video.mp4 -vn -acodec copy ~/video/audioFile.m4a 从video.mp4中提取音频到文件audioFile.m4a中 查看提取的音频文件 ffprobe ~/video/audioFile.m4a

OneDrive下的OneNote扩容方法,及查看OneDrive容量的方法(详细图文教程)

目录 一、内存不足的问题二、土豪续费扩容法三、X宝扩容法3.1 购买链接3.2 登录接口3.3 详细图文操作过程3.3.1 获取链接&#xff1a;3.3.2 用订单号和获取链接扩容&#xff1a; 3.4 扩容后的容量 四、查看自己OneDrive的容量五、总结 一、内存不足的问题 一直都在用OneNote记…

STM32H723 CubeMX 三路FDCAN 代码

时钟频率 FDCAN1 设置250kbit/s FDCAN2 设置500kbit/s FDCAN3 设置500kbit/s fdcan.c /* USER CODE BEGIN Header */ /********************************************************************************* file fdcan.c* brief This file provides code fo…

【刷题篇】回溯算法(深度优先搜索(二))

文章目录 岛屿数量电话号码的字母组合组合总和活字印刷 岛屿数量 给你一个由 ‘1’&#xff08;陆地&#xff09;和 ‘0’&#xff08;水&#xff09;组成的的二维网格&#xff0c;请你计算网格中岛屿的数量。 岛屿总是被水包围&#xff0c;并且每座岛屿只能由水平方向和/或竖直…

CentOS7.9中使用packstack安装train版本

这里写目录标题 材料准备为什么选择packstack安装静态ip系统配置使用阿里云yum源安装packstack部署openstack 安装成功和后续使用all in one模式下虚拟机外网和浮动ip原理讲解nat网桥的创建方法 材料准备 ecs云服务器8核心16g内存一台&#xff0c;系统盘100GB&#xff0c;系统…

2.2 数据通信的基础知识

前言&#xff1a; 2.2.1 数据通信的基础知识 **笔记**&#xff1a;2.2.1 数据通信系统的模型 --- **1. 数据通信系统组成**&#xff1a; - 三大部分&#xff1a; 1. 源系统 (发送端) 2. 传输系统 (传输网络) 3. 目的系统 (接收端) --- **2. 源系统**&#xff1a; -…

vue-4

一、文章内容概括 1.组件的三大组成部分&#xff08;结构/样式/逻辑&#xff09; ​ scoped解决样式冲突/data是一个函数 2.组件通信 组件通信语法父传子子传父非父子通信&#xff08;扩展&#xff09; 3.进阶语法 v-model原理v-model应用于组件sync修饰符ref和$refs$nex…

SAP SMARTFORMS 文本框显示默认浏览器

问题描述&#xff1a;新上的SAP系统SMARTFORMS文本框显示浏览器&#xff0c;导致无法拉取系统变量 解决方法&#xff1a; 类CL_COS_UTILITIES做隐式增强 IF sy-tcode SMARTFORMS.rv_is_s4h .ENDIF. 然后执行程序&#xff1a;RSCPSETEDITOR 把这俩√去掉后激活即可

MISRA C 2012 阅读笔记

背景 C语言诞生至今已有50年&#xff0c;因其语言简洁&#xff0c;语法丰富&#xff0c;可移植性高&#xff0c;和执行效率高等优点&#xff0c;至今仍保持着强大的生命力&#xff0c;在各个行业发挥着作用。 然而C语言的一些优点有时候也是一把双刃剑&#xff0c;在使用者使用…

Acwing.886 求组合数Ⅱ

题目 给定n组询问&#xff0c;每组询问给定两个整数a&#xff0c; b&#xff0c;请你输出 的值。 输入格式 第一行包含整数n。 接下来n行&#xff0c;每行包含—组a和b。 输出格式 共n行&#xff0c;每行输出—个询问的解。 数据范围 1<n≤10000, 1 <b<a≤105…

Acwing.889 满足条件的01序列

题目 给定n个0和n个1&#xff0c;它们将按照某种顺序排成长度为2n的序列&#xff0c;求它们能排列成的所有序列中&#xff0c;能够满足任意前缀序列中0的个数都不少于1的个数的序列有多少个。 输出的答案对109&#xff0b;7取模。 输入格式 共一行&#xff0c;包含整数n。 …

【python】python虚拟环境--20231008

https://blog.csdn.net/m0_69023493/article/details/129158656 安装好python和pip 略 新建python虚拟空间 安装virtualenv pip install virtualenv -i https://pypi.tuna.tsinghua.edu.cn/simple安装virtualenvwrapper-win&#xff08;可选&#xff09; pip install vir…

软件测试/测试开发丨接口测试学习笔记-常见的接口协议

点此获取更多相关资料 本文为霍格沃兹测试开发学社学员学习笔记分享 原文链接&#xff1a;https://ceshiren.com/t/topic/27726 一、网络模型 二、常见接口协议 RPC协议 RPC(remote procedure call)以本地代码调用的方式实现远程执行主要用于公司内部的服务调用 优点 传输效…

3分钟轻松实现网关网口连接罗克韦尔AB CompactLogix系列PLC

目录 EG网关网口连接罗克韦尔AB CompactLogix系列PLC 一. 准备工作 1.1 在对接前我们需准备如下物品 1.2 EG20网关准备工作 1.3 PLC准备工作 二. EMCP平台设置 2.1 新增EG设备 2.2 远程配置网关 2.3 网关绑定 2.4 通讯参数设置 2.5 创建设备驱动 2.5.1 添加变量 2.…

springcloud之项目实战搭建单体

写在前面 在上篇文章 中我们介绍了项目的整体内容以及架构&#xff0c;本文就开始实现一个单体的版本&#xff0c;在之后的文章中&#xff0c;在使用springcloud相关组件将这个单体的版本一步步的拆分为微服务的版本&#xff0c;在开始之前再贴下组件图&#xff1a; 本文我们分…

win11 vscode配置c/c++,使用mingw编译器

文章目录 第一步&#xff1a;装好vscode第二步&#xff1a;下载 mingw创建一个文件夹作为C或者C的项目文件夹&#xff0c;用vscode打开 第一步&#xff1a;装好vscode 之前使用python时装过 第二步&#xff1a;下载 mingw 官网 3.从这个界面一直往下滑 找到&#xff1a; 下…

是真的吗?Nuture子刊告诉你这么多年的微生物组经验都是错的?!

发表期刊&#xff1a;Nature Microbiology 发表时间&#xff1a;2023 影响因子&#xff1a;28.3 DOI: 10.1038/s41564-023-01426-7 在过去的二十年里&#xff0c;人们对人类微生物组研究的兴趣呈指数级增长&#xff0c;同时伴随而来的一系列相关研究的文献发表数目也是逐年递…

通过cri-o部署k8s集群环境

目录 一.基础环境配置&#xff08;每个节点都做&#xff09; 1.hosts解析 2.防火墙和selinux 3.安装基本软件并配置时间同步 4.禁用swap分区 5.更改内核参数 6.配置ipvs 7.k8s下载 &#xff08;1&#xff09;配置镜像下载相关软件 &#xff08;2&#xff09;配置kube…

B站数据分析,UP主粉丝画像如何看?

随着互联网的发展&#xff0c;在大数据时代的今天&#xff0c;越来越多的企业用它们来指导精准营销&#xff0c;数据资源成为各大公司竞相追逐的香饽饽&#xff0c;而对于短视频广告投放来说&#xff0c;了解账号的粉丝人群画像&#xff0c;就可以知道他们的喜好厌恶&#xff0…

GitHub相应太慢

后期使用到github下载源码&#xff0c;会发现响应太慢&#xff0c;本篇文章解决你的问题 获取域名对应的ip 访问链接&#xff1a;https://raw.hellogithub.com/hosts&#xff08;ps&#xff1a;这链接定时更新&#xff09;&#xff0c;获取对应的host配置。 如果需要工具自动…