当前位置: 首页 > article >正文

源码分析之Leaflet图层控制控件Control.Layers实现原理

概述

本文将介绍Leaflet库中最后一个组件,即图层控制组件 Control.Layers

源码实现

export var Layers = Control.extend({options: {collapsed: true,position: "topright",autoZIndex: true,hideSingleBase: false,sortLayers: false,sortFunction: function (layerA, layerB, nameA, nameB) {return nameA < nameB ? -1 : nameB < nameA ? 1 : 0;},},initialize: function (baseLayers, overlays, options) {Util.setOptions(this, options);this._layerControlInputs = [];this._layers = [];this._lastZIndex = 0;this._handlingClick = false;this._preventClick = false;for (var i in baseLayers) {this._addLayer(baseLayers[i], i);}for (i in overlays) {this._addLayer(overlays[i], i, true);}},onAdd: function (map) {this._initLayout();this._update();this._map = map;map.on("zoomend", this._checkDisabledLayers, this);for (var i = 0; i < this._layers.length; i++) {this._layers[i].layer.on("add remove", this._onLayerChange, this);}return this._container;},addTo: function (map) {Control.prototype.addTo.call(this, map);return this._expandIfNotCollapsed();},onRemove: function () {this._map.off("zoomend", this._checkDisabledLayers, this);for (var i = 0; i < this._layers.length; i++) {this._layers[i].layer.off("add remove", this._onLayerChange, this);}},addBaseLayer: function (layer, name) {this._addLayer(layer, name);return this._map ? this._update() : this;},addOverlay: function (layer, name) {this._addLayer(layer, name, true);return this._map ? this._update() : this;},removeLayer: function (layer) {layer.off("add remove", this._onLayerChange, this);var obj = this._getLayer(Util.stamp(layer));if (obj) {this._layers.splice(this._layers.indexOf(obj), 1);}return this._map ? this._update() : this;},expand: function () {DomUtil.addClass(this._container, "leaflet-control-layers-expanded");this._section.style.height = null;var acceptableHeight =this._map.getSize().y - (this._container.offsetTop + 50);if (acceptableHeight < this._section.clientHeight) {DomUtil.addClass(this._section, "leaflet-control-layers-scrollbar");this._section.style.height = acceptableHeight + "px";} else {DomUtil.removeClass(this._section, "leaflet-control-layers-scrollbar");}this._checkDisabledLayers();return this;},collapse: function () {DomUtil.removeClass(this._container, "leaflet-control-layers-expanded");return this;},_initLayout: function () {var className = "leaflet-control-layers",container = (this._container = DomUtil.create("div", className)),collapsed = this.options.collapsed;container.setAttribute("aria-haspopup", true);DomEvent.disableClickPropagation(container);DomEvent.disableScrollPropagation(container);var section = (this._section = DomUtil.create("section",className + "-list"));if (collapsed) {this._map.on("click", this.collapse, this);DomEvent.on(container,{mouseenter: this._expandSafely,mouseleave: this.collapse,},this);}var link = (this._layersLink = DomUtil.create("a",className + "-toggle",container));link.href = "#";link.title = "Layers";link.setAttribute("role", "button");DomEvent.on(link,{keydown: function (e) {if (e.keyCode === 13) {this._expandSafely();}},click: function (e) {DomEvent.preventDefault(e);this._expandSafely();},},this);if (!collapsed) {this.expand();}this._baseLayersList = DomUtil.create("div", className + "-base", section);this._separator = DomUtil.create("div", className + "-separator", section);this._overlaysList = DomUtil.create("div",className + "-overlays",section);container.appendChild(section);},_getLayer: function (id) {for (var i = 0; i < this._layers.length; i++) {if (this._layers[i] && Util.stamp(this._layers[i].layer) === id) {return this._layers[i];}}},_addLayer: function (layer, name, overlay) {if (this._map) {layer.on("add remove", this._onLayerChange, this);}this._layers.push({layer: layer,name: name,overlay: overlay,});if (this.options.sortLayers) {this._layers.sort(Util.bind(function (a, b) {return this.options.sortFunction(a.layer, b.layer, a.name, b.name);}, this));}if (this.options.autoZIndex && layer.setZIndex) {this._lastZIndex++;layer.setZIndex(this._lastZIndex);}this._expandIfNotCollapsed();},_update: function () {if (!this._container) {return this;}DomUtil.empty(this._baseLayersList);DomUtil.empty(this._overlaysList);this._layerControlInputs = [];var baseLayersPresent,overlaysPresent,i,obj,baseLayersCount = 0;for (i = 0; i < this._layers.length; i++) {obj = this._layers[i];this._addItem(obj);overlaysPresent = overlaysPresent || obj.overlay;baseLayersPresent = baseLayersPresent || !obj.overlay;baseLayersCount += !obj.overlay ? 1 : 0;}if (this.options.hideSingleBase) {baseLayersPresent = baseLayersPresent && baseLayersCount > 1;this._baseLayersList.style.display = baseLayersPresent ? "" : "none";}this._separator.style.display =overlaysPresent && baseLayersPresent ? "" : "none";return this;},_onLayerChange: function (e) {if (!this._handlingClick) {this._update();}var obj = this._getLayer(Util.stamp(e.target));var type = obj.overlay? e.type === "add"? "overlayadd": "overlayremove": e.type === "add"? "baselayerchange": null;if (type) {this._map.fire(type, obj);}},_createRadioElement: function (name, checked) {var radioHtml ='<input type="radio" class="leaflet-control-layers-selector" name="' +name +'"' +(checked ? ' checked="checked"' : "") +"/>";var radioFragment = document.createElement("div");radioFragment.innerHTML = radioHtml;return radioFragment.firstChild;},_addItem: function (obj) {var label = document.createElement("label"),checked = this._map.hasLayer(obj.layer),input;if (obj.overlay) {input = document.createElement("input");input.type = "checkbox";input.className = "leaflet-control-layers-selector";input.defaultChecked = checked;} else {input = this._createRadioElement("leaflet-base-layers_" + Util.stamp(this),checked);}this._layerControlInputs.push(input);input.layerId = Util.stamp(obj.layer);DomEvent.on(input, "click", this._onInputClick, this);var name = document.createElement("span");name.innerHTML = " " + obj.name;var holder = document.createElement("span");label.appendChild(holder);holder.appendChild(input);holder.appendChild(name);var container = obj.overlay ? this._overlaysList : this._baseLayersList;container.appendChild(label);this._checkDisabledLayers();return label;},_onInputClick: function () {if (this._preventClick) {return;}var inputs = this._layerControlInputs,input,layer;var addedLayers = [],removedLayers = [];this._handlingClick = true;for (var i = inputs.length - 1; i >= 0; i--) {input = inputs[i];layer = this._getLayer(input.layerId).layer;if (input.checked) {addedLayers.push(layer);} else if (!input.checked) {removedLayers.push(layer);}}for (i = 0; i < removedLayers.length; i++) {if (this._map.hasLayer(removedLayers[i])) {this._map.removeLayer(removedLayers[i]);}}for (i = 0; i < addedLayers.length; i++) {if (!this._map.hasLayer(addedLayers[i])) {this._map.addLayer(addedLayers[i]);}}this._handlingClick = false;this._refocusOnMap();},_checkDisabledLayers: function () {var inputs = this._layerControlInputs,input,layer,zoom = this._map.getZoom();for (var i = inputs.length - 1; i >= 0; i--) {input = inputs[i];layer = this._getLayer(input.layerId).layer;input.disabled =(layer.options.minZoom !== undefined && zoom < layer.options.minZoom) ||(layer.options.maxZoom !== undefined && zoom > layer.options.maxZoom);}},_expandIfNotCollapsed: function () {if (this._map && !this.options.collapsed) {this.expand();}return this;},_expandSafely: function () {var section = this._section;this._preventClick = true;DomEvent.on(section, "click", DomEvent.preventDefault);this.expand();var that = this;setTimeout(function () {DomEvent.off(section, "click", DomEvent.preventDefault);that._preventClick = false;});},
});export var layers = function (baseLayers, overlays, options) {return new Layers(baseLayers, overlays, options);
};

核心结构

export var Layers = Control.extend({...});
export var layers = function (...) { return new Layers(...) };
  • 继承自 Leaflet 的 Control 基类,实现图层控制功能。
  • 提供工厂函数 layers() 简化实例化操作。

配置项 (options)

options: {collapsed: true,          // 默认折叠position: "topright",     // 控件位置autoZIndex: true,         // 自动管理图层 z-indexhideSingleBase: false,    // 是否隐藏单一基础图层sortLayers: false,        // 是否排序图层sortFunction: (a, b) => { ... } // 自定义排序函数
}

关键配置说明

  • autoZIndex
    自动为新图层分配递增的 z-index,确保叠加顺序正确。
  • sortLayers
    启用后按 sortFunction 排序图层(默认按名称字母排序)。
  • hideSingleBase
    当仅有一个基础图层时隐藏其选项区域。

初始化 (initialize)

initialize: function (baseLayers, overlays, options) {Util.setOptions(this, options);this._layerControlInputs = [];  // 存储输入控件this._layers = [];             // 存储图层信息this._lastZIndex = 0;          // 自动 Z-Index 计数器// 添加初始图层for (var i in baseLayers) this._addLayer(baseLayers[i], i);for (i in overlays) this._addLayer(overlays[i], i, true);
}

参数说明

  • baseLayers: 基础图层对象(互斥,如地图类型切换)
  • overlays: 覆盖层对象(可叠加,如标记层)

生命周期方法

onAdd(map)

onAdd: function (map) {this._initLayout();     // 初始化 DOM 结构this._update();         // 渲染图层选项this._map = map;map.on("zoomend", this._checkDisabledLayers, this); // 监听缩放事件// 绑定图层变化事件this._layers.forEach(layer => layer.layer.on("add remove", this._onLayerChange, this));
}

onRemove()

onRemove: function () {this._map.off("zoomend", this._checkDisabledLayers, this);// 解绑图层事件this._layers.forEach(layer => layer.layer.off("add remove", this._onLayerChange, this));
}

图层管理 API

添加/移除图层

addBaseLayer(layer, name); // 添加基础图层
addOverlay(layer, name); // 添加覆盖层
removeLayer(layer); // 移除指定图层

核心逻辑方法

_addLayer(layer, name, overlay) {// 处理排序、自动 Z-Indexif (this.options.sortLayers) this._layers.sort(...);if (this.options.autoZIndex) layer.setZIndex(++this._lastZIndex);
}

DOM 与交互

控件布局 (_initLayout)

_initLayout: function () {// 创建 DOM 结构this._container = DomUtil.create("div", "leaflet-control-layers");this._section = DomUtil.create("section", "leaflet-control-layers-list");// 折叠/展开交互逻辑if (this.options.collapsed) {this._map.on("click", this.collapse);DomEvent.on(container, { mouseenter: this._expandSafely, mouseleave: this.collapse });}
}

更新逻辑 (_update)

_update: function () {// 清空并重新渲染所有选项DomUtil.empty(this._baseLayersList);DomUtil.empty(this._overlaysList);this._layers.forEach(layer => this._addItem(layer));
}

事件处理

输入控件点击 (_onInputClick)

_onInputClick: function () {// 处理图层显隐切换const addedLayers = [], removedLayers = [];this._layerControlInputs.forEach(input => {const layer = this._getLayer(input.layerId).layer;input.checked ? addedLayers.push(layer) : removedLayers.push(layer);});// 更新地图图层removedLayers.forEach(layer => this._map.removeLayer(layer));addedLayers.forEach(layer => this._map.addLayer(layer));
}

图层状态变化 (_onLayerChange)

_onLayerChange: function (e) {// 触发 Leaflet 事件:baselayerchange / overlayadd / overlayremoveconst obj = this._getLayer(Util.stamp(e.target));const eventType = obj.overlay ?(e.type === "add" ? "overlayadd" : "overlayremove") :(e.type === "add" ? "baselayerchange" : null);if (eventType) this._map.fire(eventType, obj);
}

辅助功能

动态禁用图层 (_checkDisabledLayers)

_checkDisabledLayers: function () {// 根据当前缩放级别禁用不符合条件的图层const zoom = this._map.getZoom();this._layerControlInputs.forEach(input => {const layer = this._getLayer(input.layerId).layer;input.disabled =(layer.options.minZoom !== undefined && zoom < layer.options.minZoom) ||(layer.options.maxZoom !== undefined && zoom > layer.options.maxZoom);});
}

安全展开逻辑 (_expandSafely)

_expandSafely: function () {// 临时阻止点击事件防止误操作this._preventClick = true;DomEvent.on(this._section, "click", DomEvent.preventDefault);setTimeout(() => {DomEvent.off(this._section, "click", DomEvent.preventDefault);this._preventClick = false;}, 0);
}

设计亮点

  1. 响应式设计

    • 自动根据地图缩放级别禁用不符合条件的图层选项
    • 展开时动态计算最大高度避免溢出视口
  2. 可扩展性

    • 支持通过 sortFunction 自定义图层排序规则
    • 允许通过 autoZIndex 自动管理图层叠加顺序
  3. 无障碍支持

    • 使用 aria-haspopup 标记控件
    • 支持键盘操作(通过回车键展开)

相关文章:

源码分析之Leaflet图层控制控件Control.Layers实现原理

概述 本文将介绍Leaflet库中最后一个组件&#xff0c;即图层控制组件 Control.Layers。 源码实现 export var Layers Control.extend({options: {collapsed: true,position: "topright",autoZIndex: true,hideSingleBase: false,sortLayers: false,sortFunction:…...

嵌入式软硬件开发,常见通信总线

嵌入式通信总线分类与应用指南 一、片上/板级通信接口&#xff08;内部互联&#xff09; I2C总线 核心特性 同步半双工传输&#xff0c;SCL时钟线SDA数据线7/10位地址寻址&#xff0c;支持多主多从架构标准模式100kbps&#xff0c;高速模式3.4Mbps&#xff0c;超高速模式5Mbps…...

[ERROR] Some problems were encountered while processing the POMs

记录一次maven的错误 问题复现&#xff1a; 我在ruoyi-vue-plus项目的ruoyi-modules中新建了一个子项目ruoyi-network-telphonem,然后某一次编译的时候提示SysTenantServiceImpl找不到无参的构造函数&#xff0c;检查了很久都没发现问题&#xff0c;于是我想着删掉本地maven仓…...

Ubuntu 服务器上运行相关命令,关闭终端就停止服务,怎么才能启动后在后台运行?

环境&#xff1a; Ubuntu 20.04 LTS 问题描述&#xff1a; Ubuntu 服务器上运行相关命令&#xff0c;关闭终端就停止服务&#xff0c;怎么才能启动后在后台运行&#xff1f; bash docker/entrypoint.sh解决方案&#xff1a; bash docker/entrypoint.sh 脚本在后台运行&…...

前端工具方法整理

文章目录 1.在数组中找到匹配项&#xff0c;然后创建新对象2.对象转JSON字符串3.JSON字符串转JSON对象4.有个响应式对象&#xff0c;然后想清空所有属性5.判断参数不为空6.格式化字符串7.解析数组内容用逗号拼接 1.在数组中找到匹配项&#xff0c;然后创建新对象 const modifi…...

关于Deepseek本地AI知识文档库被联网访问方法的探索

背景&#xff1a; 根据前面的文章&#xff0c;我们使用了anythingLLM搭建了本地知识库&#xff0c;这个虽然基本可以用了&#xff0c;但是你只能在anythingLLM的界面里面进行提问&#xff0c;自能自己用&#xff0c;那么能否让其他人也可以使用我们搭建的本地知识库呢根据我的…...

一个简单的跨平台Python GUI自动化 AutoPy

象一下&#xff0c;你坐在电脑前&#xff0c;手指轻轻一点&#xff0c;鼠标自己动了起来&#xff0c;键盘仿佛被无形的手操控&#xff0c;屏幕上的任务自动完成——这一切不需要你费力&#xff0c;只靠几行代码就能实现。这就是AutoPy的魅力&#xff0c;一个简单却强大的跨平台…...

面试题汇总06-场景题线上问题排查难点亮点

面试题汇总06-场景题&线上问题排查&难点亮点 【一】场景题【1】订单到期关闭如何实现【2】每天100w次登录请求,4C8G机器如何做JVM调优?(1)问题描述和分析(2)堆内存设置(3)垃圾收集器选择(4)各区大小设置(5)添加必要的日志【3】如果你的业务量突然提升100倍…...

【嵌入式系统设计师】知识点:第4章 嵌入式系统软件基础知识

提示:“软考通关秘籍” 专栏围绕软考展开,全面涵盖了如嵌入式系统设计师、数据库系统工程师、信息系统管理工程师等多个软考方向的知识点。从计算机体系结构、存储系统等基础知识,到程序语言概述、算法、数据库技术(包括关系数据库、非关系型数据库、SQL 语言、数据仓库等)…...

基于RDK X3的“校史通“机器人:SLAM导航+智能交互,让校史馆活起来!

视频标题&#xff1a; 【校史馆の新晋顶流】RDK X3机器人&#xff1a;导览员看了直呼内卷 视频文案&#xff1a; 跑得贼稳团队用RDK X3整了个大活——给校史馆造了个"社牛"机器人&#xff01; 基于RDK X3开发板实现智能导航与语音交互SLAM技术让机器人自主避障不…...

春芽儿智能跳绳:以创新技术引领运动健康新潮流

在全球运动健康产业蓬勃发展的浪潮中&#xff0c;智能健身器材正成为连接科技与生活的重要纽带。据《中国体育用品产业发展报告》显示&#xff0c;2023年中国智能运动装备市场规模突破千亿元&#xff0c;其中跳绳类目因兼具大众普及性与技术升级空间&#xff0c;年均增速超30%。…...

复活之我会二分

文章目录 整数二分模板模板1&#xff1a;满足条件的第一个数模板2&#xff1a;满足条件的最后一个数 浮点数二分模板一、Building an Aquarium思路分析具体代码 二、Tracking Segments思路分析具体代码 三、Wooden Toy Festival思路分析具体代码 四、路标设置思路分析具体代码 …...

NOA是什么?国内自动驾驶技术的现状是怎么样的?

国内自动驾驶技术的现状如何&#xff1f; 汽车的NOA指的是“Navigate on Autopilot”&#xff0c;即导航辅助驾驶或领航辅助驾驶。这是一种高级驾驶辅助系统&#xff08;ADAS&#xff09;的功能&#xff0c;它允许车辆在设定好起点和终点后&#xff0c;自动完成行驶、超车、变…...

秒杀系统的性能优化

秒杀任务总体QPS预期是每秒几十万&#xff0c;对tomcat、redis、JVM参数进行优化。 tomcat线程数 4核8G的机器&#xff0c;一般就是开200-300个工作线程&#xff0c;这是个经验值。每秒一个线程处理3-5个请求&#xff0c;200多个线程的QPS可以达到1000左右。线程不能太多&…...

Linux 指令初探:开启终端世界的大门

前言 当我们初次接触 Linux&#xff0c;往往会被一串串在黑底屏幕中跳动的字符震撼甚至吓退。然而&#xff0c;正是这些看似晦涩的命令&#xff0c;构建了服务器、嵌入式系统乃至云计算的世界。 本篇将带你从最基础的 Linux 指令开始&#xff0c;逐步揭开命令行的神秘面纱。从…...

Edge浏览器IE兼容模式设置

一、了解Edge浏览器的IE模式 Microsoft Edge&#xff0c;作为微软推出的新一代浏览器&#xff0c;不仅拥有更快的浏览速度、更强大的安全性能以及更现代的界面设计&#xff0c;还巧妙地解决了与旧网站和应用程序的兼容性问题。通过内置的IE模式&#xff0c;Edge能够模拟IE浏览器…...

文件中魔数

当然可以&#xff0c;来讲几个实际开发中魔数会“救你一命”的场景&#xff0c;帮助你更直观地理解它的作用。 &#x1f3af; 场景 1&#xff1a;误读取非 SST 文件 假设你有一段代码在扫描一个目录&#xff0c;尝试打开所有 .sst 后缀的文件并加载&#xff1a; cpp 复制 编辑…...

制定大运维管理体系的标准、流程、机制、规范

规划并制定大运维管理体系的标准、流程、机制、规范&#xff0c;对于确保平台的可用性和稳定性至关重要。这一过程涉及从顶层设计到具体执行的全面考量&#xff0c;需要综合考虑业务需求、技术架构、团队能力等多方面因素。以下是一个基本框架&#xff0c;用于指导如何构建有效…...

算法初识-时间复杂度空间复杂度

注&#xff1a;观看Adbul Bari算法视频 算法概念 算法&#xff1a;先验分析&#xff0c;不依托于硬件&#xff0c;无语言限制&#xff0c;逻辑。 程序&#xff1a;后验测试&#xff0c;依托硬件&#xff0c;语言限制&#xff0c;实现。 特点&#xff1a; 输入-0或多个输出-至…...

Python高阶函数-sorted(深度解析从原理到实战)

一、sorted()函数概述 sorted()是Python内置的高阶函数&#xff0c;用于对可迭代对象进行排序操作。与列表的sort()方法不同&#xff0c;sorted()会返回一个新的已排序列表&#xff0c;而不改变原数据。 基本语法 sorted(iterable, *, keyNone, reverseFalse)二、核心参数详…...

Vue3实战三、Axios封装结合mock数据、Vite跨域及环境变量配置

目录 Axios封装、调用mock接口、Vite跨域及环境变量配置封装Axios对象调用mock接口数据第一步、安装axios&#xff0c;处理一部请求第二步、创建request.ts文件第三步、本地模拟mock数据接口第四步、测试axiosmock接口是否可以调用第五步、自行扩展 axios 返回的数据类型 axios…...

机器学习(神经网络基础篇)——个人理解篇5(梯度下降中遇到的问题)

在神经网络训练中&#xff0c;计算参数的梯度是关键步骤。numerical_gradient 方法旨在通过数值微分&#xff08;中心差分法&#xff09;计算损失函数对网络参数的梯度。然而&#xff0c;该方法的实现存在一个关键问题&#xff0c;导致梯度计算错误。 1、错误代码示例&#xf…...

sklearn的Pipeline

Pipeline类 介绍:Pipeline 可以将多个数据处理步骤和机器学习模型组合成一个序列,其中每个步骤都是一个变换器(Transformer)或者估计器(Estimator),并且Pipeline中的最后一个必须为估计器,其它的必须为变换器,如果Pipeline中的估计器为为分类器则整个Pipeline就作为分…...

【Linux】虚拟机设置静态IP

主播我今天下午学了几节微服务课&#xff0c;上课的时候&#xff0c;直接把手机拿走了去上课&#xff08;电脑连的我手机的热点&#xff09;&#xff0c;虚拟机没关&#xff0c;晚上主播我回来继续学&#xff0c;电脑连上热点之后&#xff0c;发现虚拟机连接不上了&#xff0c;…...

职坐标解析自动驾驶技术发展新趋势

内容概要 作为智能交通革命的核心驱动力&#xff0c;自动驾驶技术正以惊人的速度重塑出行生态。2023年&#xff0c;行业在多传感器融合与AI算法优化两大领域实现突破性进展&#xff1a;激光雷达、摄像头与毫米波雷达的协同精度提升至厘米级&#xff0c;而深度学习模型的实时决…...

js算法基础-01

文章目录 1、双指针2、快慢指针3、滑动指针4、哈希表5、汇总区间6、栈7、进制求和8、数学9、动态规划 js算法基础, 每个重要逻辑思路&#xff0c;做一下列举 1、双指针 有序数组合并&#xff1a;一般思路就是合并、排序&#xff0c;当然效率略低题目1&#xff1a;nums1中取前m个…...

了解 DeepSeek R1

了解DeepSeek R1 R1探索纯强化学习是否可以在没有监督微调的情况下学会推理的能力。 ‘Aha’ Moment 这种现象有点类似于人类在解决问题时突然意识到的方式&#xff0c;以下是它的工作原理&#xff1a; 初始尝试&#xff1a;模型对解决问题进行初始尝试识别&#xff1a;识别…...

局域网:电脑或移动设备作为主机实现局域网访问

电脑作为主机 1. 启用电脑的网络发现、SMB功能 2. 将访问设备开启WIFI或热点&#xff0c;用此电脑连接&#xff1b;或多台设备连接到同一WIFI 3. 此电脑打开命令行窗口&#xff0c;查看电脑本地的IP地址 Win系统&#xff1a;输入"ipconfig"&#xff0c;回车后如图 4.…...

小型园区组网图

1. 在小型园区中&#xff0c;S5735-L-V2通常部署在网络的接入层&#xff0c;S8700-4通常部署在网络的核心&#xff0c;出口路由器一般选用AR系列路由器。 2. 接入交换机与核心交换机通过Eth-Trunk组网保证可靠性。 3. 每个部门业务划分到一个VLAN中&#xff0c;部门间的业务在C…...

数据分享:汽车测评数据

说明&#xff1a;如需数据可以直接到文章最后关注获取。 1.数据背景 Car Evaluation汽车测评数据集是一个经典的机器学习数据集&#xff0c;最初由 Marko Bohanec 和 Blaz Zupan 创建&#xff0c;并在 1997 年发表于论文 "Classifier learning from examples: Common …...