Typescript中如何让input输入框接受数值类型以绘制D3散点图?
问题根因
- 输入值获取时机错误:
onBeforeShow是侧边栏即将显示时触发的生命周期函数,你在这个阶段读取了两个输入框的value,此时用户还未完成输入,点击提交时拿到的永远是侧边栏刚打开时的初始值,不是用户输入后的最新值 - 数据类型未转换:输入框的value默认是string类型,未转成number就存入数组,d3的线性比例尺计算坐标时会出错
- 数据集结构错误:
dataset1要求的是number[][]类型,每一项是[x,y]组成的子数组,你现在直接把两个值分别push,会把数组变成[x值, y值],不符合渲染要求的结构 - 重复渲染图表:每次点击提交都会新建scatterGraph实例,往容器里追加新的SVG,多次提交会出现多个重复图表
- 输入框未限制数值类型:没有给input加
type="number"限制,用户可以输入非数值内容
修复方案
1. 修改MlProvSidebar.ts代码
调整输入框属性
给两个输入框添加数值类型限制:
const metric = '<input size = "15" id = "hyper1" type="number"> <input size = "15" id = "hyper2" type="number"> <button id = "submitButton" style = "border-radius: 15px;"> Submit </button> <div style = "margin-bottom: 1cm;"></div>';
重写onBeforeShow逻辑
把取值逻辑移到点击回调内部,同时做类型转换和结构校验:
protected onBeforeShow(msg: Message): void { console.debug(`Opening ${TITLE} sidebar.`); const element = document.getElementById( 'submitButton' ) as HTMLButtonElement; element?.addEventListener('click', () => { // 点击提交时再取最新的输入值,同时转成数字 const hyperInput = Number((document.getElementById('hyper1') as HTMLInputElement).value); const hyperInput2 = Number((document.getElementById('hyper2') as HTMLInputElement).value); // 校验数值合法性 if (!isNaN(hyperInput) && !isNaN(hyperInput2)) { // 按要求的二维数组结构存入数据 dataset1.push([hyperInput, hyperInput2]); // 清空旧图表后重新渲染 d3.select('#my_dataviz').html(''); new scatterGraph(); } }); }
2. 优化scatterGraph类(可选)
在构造函数开头加清空容器逻辑,避免重复渲染,即使其他地方调用也不会出问题:
export class scatterGraph { constructor() { // 先清空容器,避免重复生成SVG d3.select('#my_dataviz').html(''); // 原有剩余逻辑保持不变 // ... } }
内容的提问来源于stack exchange,提问作者NevMthw
相关产品推荐
相关产品推荐

