You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
859 lines
31 KiB
859 lines
31 KiB
2 months ago
|
class TwdToWatData{
|
||
|
constructor(event,data){
|
||
|
this.event = event;
|
||
|
this.data = data ;
|
||
|
|
||
|
}
|
||
|
|
||
|
static GetQueryString(name){
|
||
|
var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)");
|
||
|
var r = window.location.search.substr(1).match(reg);
|
||
|
if(r!=null){
|
||
|
return unescape(r[2]);
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
static feedbackDataToWat(data){
|
||
|
return window.parent.top.DxURLPage.action(TwdToWatData.GetQueryString('strwinid'),TwdToWatData.GetQueryString('strctrid'),data);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
class TemperatureList{
|
||
|
constructor(args){
|
||
|
this.width = args.width||1000;
|
||
|
this.height = args.height||1000;
|
||
|
this.leftPadding = args.leftPadding||150;
|
||
|
this.topPadding = args.topPadding||150;
|
||
|
this.rightPadding = args.rightPadding||10;
|
||
|
this.bottomPadding = args.bottomPadding||20
|
||
|
this.showScale = args.showScale||false;
|
||
|
this.halveNum= 0;
|
||
|
this.tempListYdata=null;
|
||
|
this.xScale = null;
|
||
|
this.xAxis = null;
|
||
|
this.yAxis = null;
|
||
|
this.yScale = null;
|
||
|
this.svg = d3.select("#scd")
|
||
|
.append('g').attr("id", "g1");
|
||
|
this.widthActual = null;
|
||
|
this.xDomain = 7;
|
||
|
this.xStartIndex = 2;
|
||
|
this.xEndIndex = 8;
|
||
|
this.widthSm = null;
|
||
|
this.isNumber = function(obj){
|
||
|
let vRegx = /[0-9]/;
|
||
|
return vRegx.test(obj);
|
||
|
}
|
||
|
this.makeLine = function(svg,xSc,ySc,x1,y1,x2,y2){
|
||
|
svg.append("line")
|
||
|
.attr("x1",xSc(x1+0.5))
|
||
|
.attr("y1",ySc(y1))
|
||
|
.attr("x2",xSc(x2+0.5))
|
||
|
.attr("y2",ySc(y2))
|
||
|
.attr("style","stroke:rgb(255,0,0);stroke-width:1")
|
||
|
.classed("outerData",true);
|
||
|
}
|
||
|
this.datePonits=null;
|
||
|
this.tips = this.svg.append ('g')
|
||
|
.attr ('class', 'tips')
|
||
|
.style('display','block')
|
||
|
// this.tipsRect = this.tips.append ('path')
|
||
|
// .attr ('class' , 'tips-border' )
|
||
|
// .attr ('d' , 'm5.99786,9.79993l0,0c0,-2.65063 2.97544,-4.79938 6.64583,-4.79938l3.02083,0l0,0l14.49999,0l27.18748,0c1.76259,0 3.45298,0.50565 4.69932,1.40571c1.24633,0.90006 1.94652,2.1208 1.94652,3.39368l0,11.99845l0,0l0,7.19907l0,0c0,2.65063 -2.97544,4.79938 -6.64583,4.79938l-27.18748,0l-18.94245,12.20371l4.44246,-12.20371l-3.02083,0c-3.67039,0 -6.64583,-2.14875 -6.64583,-4.79938l0,0l0,-7.19907l0,0l0,-11.99845z' )
|
||
|
// .attr('fill','none')
|
||
|
// .attr("opacity","0.3")
|
||
|
this.tipsRect = this.tips.append('rect')
|
||
|
.attr('width','115px')
|
||
|
.attr('height','75px')
|
||
|
.attr('rx','5')
|
||
|
.attr('fill','none')
|
||
|
|
||
|
this.tipsText = this.tips.append ('text')
|
||
|
.attr('class' ,'tips-text')
|
||
|
.attr( 'x' , 6 )
|
||
|
.attr( 'y' , 25 )
|
||
|
.attr( 'fill',"white")
|
||
|
.attr('font-size','14px')
|
||
|
.text ( '' ) ;
|
||
|
|
||
|
this.render();
|
||
|
|
||
|
}
|
||
|
//入口
|
||
|
render(){
|
||
|
const _this = this
|
||
|
d3.json('./TemperatureList.json?3').then(function(data){
|
||
|
_this.tempListYdata = data.content
|
||
|
_this.date=data.date;
|
||
|
data.content.forEach(function(dataSingle){
|
||
|
_this.halveNum += dataSingle.length
|
||
|
})
|
||
|
//图表框架
|
||
|
_this.initXaxris()
|
||
|
_this.initYaxris()
|
||
|
_this.initDatePoint();
|
||
|
_this.initXGrid()
|
||
|
_this.initYGrid()
|
||
|
//计算整体网格宽度
|
||
|
_this.calculateTotalWidth()
|
||
|
//特定网格
|
||
|
_this.initLine()
|
||
|
//表头的线
|
||
|
_this.initTrLine()
|
||
|
//表头的文字
|
||
|
_this.initTrText()
|
||
|
//红色线的渲染
|
||
|
// _this.redLineInit()
|
||
|
_this.initTemperatureScale();
|
||
|
//渲染完毕后回调给框架,接受后台数据
|
||
|
let cbData = new TwdToWatData("load","");
|
||
|
TwdToWatData.feedbackDataToWat(JSON.stringify(cbData));
|
||
|
//渲染完毕后回调给框架,接受后台数据
|
||
|
})
|
||
|
|
||
|
}
|
||
|
//渲染表格
|
||
|
initXaxris(){
|
||
|
this.xScale = d3.scaleLinear()
|
||
|
//输入范围
|
||
|
.domain([0,this.xDomain+1])
|
||
|
//输出范围
|
||
|
.range([this.leftPadding,this.width-this.rightPadding]);
|
||
|
this.xAxis = d3.axisTop().scale(this.xScale).ticks(this.xDomain).tickSize(0)
|
||
|
if(!this.showScale){
|
||
|
this.xAxis.tickFormat("")
|
||
|
}
|
||
|
this.svg.append('g')
|
||
|
.call(this.xAxis)
|
||
|
.classed('axis_x', true)
|
||
|
.attr('transform',`translate(0,${this.topPadding})`)
|
||
|
|
||
|
}
|
||
|
initYaxris(){
|
||
|
this.yScale = d3.scaleLinear()
|
||
|
//输入范围
|
||
|
.domain([0,this.halveNum])
|
||
|
//输出范围
|
||
|
.range([this.topPadding,this.height-this.bottomPadding]);
|
||
|
this.yAxis = d3.axisLeft()
|
||
|
.scale(this.yScale)
|
||
|
.ticks(this.halveNum)
|
||
|
.tickSize(0)
|
||
|
if(!this.showScale){
|
||
|
this.yAxis.tickFormat("")
|
||
|
}
|
||
|
this.svg.append('g')
|
||
|
.call(this.yAxis)
|
||
|
.classed('axis_y', true)
|
||
|
.attr('transform',`translate(${this.leftPadding},0)`)
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
}
|
||
|
//渲染日期时间点,和备注
|
||
|
initDatePoint(){
|
||
|
let xSc = this.xScale;
|
||
|
let ySc = this.yScale;
|
||
|
let svg = this.svg;
|
||
|
//初始化日期点
|
||
|
let datePoints =this.date;
|
||
|
for(let i =1;i<8;i++){
|
||
|
let resDs = datePoints.map((d,index )=>[d>9?xSc(i+(index)/6):xSc(i+(index+0.3)/6),ySc(3.8),d]);
|
||
|
svg.append('g')
|
||
|
.selectAll("#date").data(resDs).enter()
|
||
|
.append("text")
|
||
|
.attr("x",d=>d[0])
|
||
|
.attr("y",d=>d[1])
|
||
|
.attr("style","font-size:12px;")
|
||
|
.text(d=>d[2]);
|
||
|
}
|
||
|
svg.append('g')
|
||
|
.append("text")
|
||
|
.attr("x",xSc(0))
|
||
|
.attr("y",ySc(this.halveNum+1))
|
||
|
.attr("style","font-size:14px;")
|
||
|
.text("腋表:");
|
||
|
svg.append("use")
|
||
|
.attr("href","#T")
|
||
|
.attr("transform","translate("+xSc(0.4)+","+ySc(this.halveNum+1-0.4)+")")
|
||
|
svg.append('g')
|
||
|
.append("text")
|
||
|
.attr("x",xSc(0.5))
|
||
|
.attr("y",ySc(this.halveNum+1))
|
||
|
.attr("style","font-size:14px;")
|
||
|
.text("脉搏:");
|
||
|
svg.append("use")
|
||
|
.attr("href","#P")
|
||
|
.attr("transform","translate("+xSc(0.9)+","+ySc(this.halveNum+1-0.2)+")")
|
||
|
svg.append('g')
|
||
|
.append("text")
|
||
|
.attr("x",xSc(1))
|
||
|
.attr("y",ySc(this.halveNum+1))
|
||
|
.attr("style","font-size:14px;")
|
||
|
.text("心率:");
|
||
|
svg.append("use")
|
||
|
.attr("href","#HR")
|
||
|
.attr("transform","translate("+xSc(1.4)+","+ySc(this.halveNum+1-0.2)+")")
|
||
|
}
|
||
|
//渲染网格
|
||
|
initXGrid(){
|
||
|
d3.selectAll(".axis_x .tick")
|
||
|
.append("line")
|
||
|
.classed("grid-line", true)
|
||
|
.attr('stroke', 'black')
|
||
|
.attr('x1',0)
|
||
|
.attr( 'y1',0)
|
||
|
.attr( 'x2',0)
|
||
|
.attr('y2',this.height-this.topPadding-this.bottomPadding)
|
||
|
}
|
||
|
initYGrid(){
|
||
|
d3.selectAll(".axis_y .tick")
|
||
|
.append("line")
|
||
|
.classed("grid-line", true)
|
||
|
.attr('stroke', 'black')
|
||
|
.attr('x1',0)
|
||
|
.attr( 'y1',0)
|
||
|
.attr( 'x2',(this.width-this.rightPadding-this.leftPadding))
|
||
|
.attr( 'y2',0)
|
||
|
}
|
||
|
//渲染特定网格
|
||
|
initLine(){
|
||
|
for(let i=this.xStartIndex;i<=this.xEndIndex;i++){
|
||
|
let startY = d3.select(`.axis_x .tick:nth-of-type(${i})`)._groups[0][0].transform.animVal[0].matrix.e
|
||
|
for(let j=4;j<49;j++){
|
||
|
this.initYLine(startY,this.widthSm,j,j<46?'darkgray':'black',j<48?6:2)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for(let j=4;j<46;j++){
|
||
|
this.initXLine(this.widthSm,j,'darkgray',1)
|
||
|
}
|
||
|
|
||
|
for(let j=5;j<46;j++){
|
||
|
d3.select(`.axis_y .tick:nth-of-type(${j})`).attr('opacity',0)
|
||
|
}
|
||
|
d3.select('.axis_y .tick:nth-of-type(47)').attr('opacity',0)
|
||
|
d3.select('.axis_y .tick:nth-of-type(56)').attr('opacity',0)
|
||
|
}
|
||
|
initXLine(w,n){
|
||
|
let appendYEle = d3.selectAll('.axis_y')
|
||
|
let xStart = d3.select(`.axis_y .tick:nth-of-type(${n})`)._groups[0][0].transform.animVal[0].matrix.f
|
||
|
let xEnd = d3.select(`.axis_y .tick:nth-of-type(${(n+1)}`)._groups[0][0].transform.animVal[0].matrix.f
|
||
|
appendYEle.append('g')
|
||
|
.attr('transform',`translate(${w},${((xEnd-xStart)+xStart)})`)
|
||
|
.append('line')
|
||
|
.attr('fill','none')
|
||
|
// .attr('stroke',n===30?'red':((n===5||(n-5)%5===0)?'black':((n===7||(n-7)%7===0)?'black':'darkgray')))
|
||
|
.attr('stroke',(n===5||(n-5)%5===0)?'black':'darkgray')
|
||
|
.attr('x1',0)
|
||
|
.attr('y1',0)
|
||
|
.attr('x2',this.widthActual-w)
|
||
|
.attr('y2',0)
|
||
|
//'darkgray'
|
||
|
if(n > 4) {
|
||
|
appendYEle.append('g')
|
||
|
.attr('transform',`translate(${w},${((xEnd-xStart)/4+xStart)})`)
|
||
|
.append('line')
|
||
|
.attr('fill','none')
|
||
|
.attr('stroke','darkgray')
|
||
|
.attr('x1',0)
|
||
|
.attr('y1',0)
|
||
|
.attr('x2',this.widthActual-w)
|
||
|
.attr('y2',0)
|
||
|
|
||
|
if(n === 8 || (n-8)%5===0) {
|
||
|
appendYEle.append('g')
|
||
|
.attr('transform',`translate(${w},${((xEnd-xStart)/2+xStart)})`)
|
||
|
.append('line')
|
||
|
.attr('fill','none')
|
||
|
.attr('stroke',(n===18 || n === 23)?'red':'black')
|
||
|
.attr('x1',0)
|
||
|
.attr('y1',0)
|
||
|
.attr('x2',this.widthActual-w)
|
||
|
.attr('y2',0)
|
||
|
}else{
|
||
|
appendYEle.append('g')
|
||
|
.attr('transform',`translate(${w},${((xEnd-xStart)/2+xStart)})`)
|
||
|
.append('line')
|
||
|
.attr('fill','none')
|
||
|
.attr('stroke','darkgray')
|
||
|
.attr('x1',0)
|
||
|
.attr('y1',0)
|
||
|
.attr('x2',this.widthActual-w)
|
||
|
.attr('y2',0)
|
||
|
}
|
||
|
//n===28 || //60脉搏这条线
|
||
|
// if(n == 29) {
|
||
|
// appendYEle.append('g')
|
||
|
// .attr('transform',`translate(${w},${(((xEnd-xStart)/2+(xEnd-xStart)/4)+xStart)})`)
|
||
|
// .append('line')
|
||
|
// .attr('fill','none')
|
||
|
// .attr('stroke','red')
|
||
|
// .attr('x1',0)
|
||
|
// .attr('y1',0)
|
||
|
// .attr('x2',this.widthActual-w)
|
||
|
// .attr('y2',0)
|
||
|
// }else{
|
||
|
appendYEle.append('g')
|
||
|
.attr('transform',`translate(${w},${(((xEnd-xStart)/2+(xEnd-xStart)/4)+xStart)})`)
|
||
|
.append('line')
|
||
|
.attr('fill','none')
|
||
|
.attr('stroke','darkgray')
|
||
|
.attr('x1',0)
|
||
|
.attr('y1',0)
|
||
|
.attr('x2',this.widthActual-w)
|
||
|
.attr('y2',0)
|
||
|
// }
|
||
|
|
||
|
|
||
|
}
|
||
|
}
|
||
|
initYLine(y,w,n,color,yNum){
|
||
|
let appendXEle = d3.selectAll('.axis_x')
|
||
|
let x = d3.select(`.axis_y .tick:nth-of-type(${n})`)._groups[0][0].transform.animVal[0].matrix.f
|
||
|
let xEnd = d3.select(`.axis_y .tick:nth-of-type(${(n+1)})`)._groups[0][0].transform.animVal[0].matrix.f
|
||
|
for(let i=1;i<yNum;i++){
|
||
|
appendXEle.append('g')
|
||
|
.attr('transform',`translate(${(y+w/yNum*i)},${(x-this.topPadding)})`)
|
||
|
.append('line')
|
||
|
.attr('fill','none')
|
||
|
.attr('stroke',color)
|
||
|
.attr('x1',0)
|
||
|
.attr('y1',0)
|
||
|
.attr('x2',0)
|
||
|
.attr('y2',(xEnd-x))
|
||
|
}
|
||
|
}
|
||
|
//渲染其它线段
|
||
|
initTrLine(){
|
||
|
let x = d3.select('.axis_y .tick:nth-of-type(4)')._groups[0][0].transform.animVal[0].matrix.f
|
||
|
let xEnd = d3.select('.axis_y .tick:nth-of-type(46)')._groups[0][0].transform.animVal[0].matrix.f
|
||
|
let y = d3.select('.axis_x .tick:nth-of-type(1)')._groups[0][0].transform.animVal[0].matrix.e
|
||
|
let yEnd = d3.select('.axis_x .tick:nth-of-type(2)')._groups[0][0].transform.animVal[0].matrix.e
|
||
|
let appendXEle = d3.selectAll('.axis_x')
|
||
|
let appendYEle = d3.selectAll('.axis_y')
|
||
|
let gridWidth = (xEnd-x)/this.tempListYdata[3].length
|
||
|
//渲染脉搏与体温的分割线
|
||
|
appendXEle.append('g')
|
||
|
.attr('transform',`translate(${(this.widthSm/2+this.leftPadding)},${(x-this.topPadding+gridWidth)})`)
|
||
|
.append('line')
|
||
|
.attr('fill','none')
|
||
|
.attr('stroke','black')
|
||
|
.attr('x1',0)
|
||
|
.attr('y1',0)
|
||
|
.attr('x2',0)
|
||
|
.attr('y2',(xEnd-x-gridWidth))
|
||
|
//渲染时间与脉搏/体温的分割线
|
||
|
appendYEle.append('g')
|
||
|
.attr('transform',`translate(0,${(x+gridWidth)})`)
|
||
|
.append('line')
|
||
|
.attr('fill','none')
|
||
|
.attr('stroke','black')
|
||
|
.attr('x1',0)
|
||
|
.attr('y1',0)
|
||
|
.attr('x2',this.widthSm)
|
||
|
.attr('y2',0)
|
||
|
//渲染最底部分割线
|
||
|
// appendYEle.append('g')
|
||
|
// .attr('transform',`translate(0,${(this.height+this.topPadding)})`)
|
||
|
// .append('line')
|
||
|
// .attr('fill','none')
|
||
|
// .attr('stroke','black')
|
||
|
// .attr('x1',0)
|
||
|
// .attr('y1',0)
|
||
|
// .attr('x2',this.width)
|
||
|
// .attr('y2',0)
|
||
|
}
|
||
|
//渲染特定网格内的文字
|
||
|
initTrText() {
|
||
|
var count = 0;
|
||
|
let len = this.tempListYdata.length;
|
||
|
for(let i =0;i<len;i++){
|
||
|
this.appendText(this.tempListYdata[i].name,(this.widthSm/2)+this.leftPadding,this.calculateHeight(count+1))
|
||
|
count+=this.tempListYdata[i].length;
|
||
|
}
|
||
|
//网格文字渲染
|
||
|
let j = 52.3;
|
||
|
let k = 6;
|
||
|
//时间
|
||
|
this.appendText('时 间',this.widthSm/2+this.leftPadding,this.calculateHeight(4))
|
||
|
//脉搏
|
||
|
this.appendText('脉 搏',(this.widthSm/2-this.widthSm/4+this.leftPadding),this.calculateHeight(5))
|
||
|
this.appendText('次/分',(this.widthSm/2-this.widthSm/4+this.leftPadding),this.calculateHeight(5.8))
|
||
|
|
||
|
for(let i=180;i>=40;i=i-10){
|
||
|
this.appendText(`${i}`,(this.widthSm/2-this.widthSm/4+this.leftPadding),this.calculateMBHeight(j))
|
||
|
j=j+(i===180?4:5)
|
||
|
}
|
||
|
//体温
|
||
|
this.appendText('体 温',(this.widthSm/2+this.widthSm/4+this.leftPadding),this.calculateHeight(5))
|
||
|
this.appendText('℃',(this.widthSm/2+this.widthSm/4+this.leftPadding),this.calculateHeight(5.8))
|
||
|
for(let i=43;i>=34;i--){
|
||
|
if(i != 43 && i != 42) {
|
||
|
this.appendText(`${i}`,(this.widthSm/2+this.widthSm/4+this.leftPadding),this.calculateTwHeight(k))
|
||
|
}
|
||
|
k=k+5
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//计算特定网格里文字的y定位
|
||
|
calculateMBHeight(n){
|
||
|
return (this.height-this.topPadding-this.bottomPadding)/this.halveNum/4*n-5+30
|
||
|
}
|
||
|
|
||
|
//计算特定网格里文字的y定位
|
||
|
calculateHeight(n){
|
||
|
return (this.height-this.topPadding-this.bottomPadding)/this.halveNum*n-5
|
||
|
}
|
||
|
|
||
|
//计算特定网格里文字的y定位
|
||
|
calculateTwHeight(n){
|
||
|
return (this.height-this.topPadding-this.bottomPadding)/this.halveNum/2*n-5
|
||
|
}
|
||
|
|
||
|
//渲染特定网格里文字方法的封装
|
||
|
appendText(name,transWidth,transHeight){
|
||
|
this.svg.select("#g1 .axis_x").append('g')
|
||
|
.attr('transform', `translate(${transWidth},${transHeight})`)
|
||
|
.append("text").text(`${name}`)
|
||
|
.attr("style","font-size:12px;")
|
||
|
.attr('fill','black')
|
||
|
.attr('stroke','none')
|
||
|
}
|
||
|
//计算可视区域网格的宽度
|
||
|
calculateTotalWidth(){
|
||
|
let xStart = d3.select('.axis_x .tick:nth-of-type(1)')._groups[0][0].transform.animVal[0].matrix.e
|
||
|
let xEnd = d3.select(`.axis_x .tick:nth-of-type(${(this.xDomain+2)}`)._groups[0][0].transform.animVal[0].matrix.e
|
||
|
this.widthActual = xEnd - xStart;
|
||
|
this.widthSm = this.widthActual/(this.xDomain+1)
|
||
|
}
|
||
|
//红色线的处理
|
||
|
redLineInit(){
|
||
|
for(let i=3;i<=this.xDomain+1;i++){
|
||
|
d3.select(`.axis_x .tick:nth-of-type(${i}) .grid-line`)
|
||
|
.attr('stroke','red')
|
||
|
}
|
||
|
}
|
||
|
/**
|
||
|
* 初始化体温的坐标系
|
||
|
*/
|
||
|
initTemperatureScale(){
|
||
|
//划线部分的X轴坐标
|
||
|
let begin = this.leftPadding + (1/(this.xDomain+1))*(this.width-this.rightPadding-this.leftPadding)
|
||
|
this.dateScale = d3.scaleLinear()
|
||
|
//输入范围
|
||
|
.domain([0,this.xDomain*6])
|
||
|
//输出范围
|
||
|
.range([begin,this.width-this.rightPadding]);
|
||
|
this.dateXAxis = d3.axisTop().scale(this.dateScale).ticks(this.xDomain*6);
|
||
|
let translateY = this.topPadding + (45/(this.halveNum*2))*(this.height-this.bottomPadding-this.topPadding)
|
||
|
this.svg.append('g')
|
||
|
.call(this.dateXAxis)
|
||
|
.classed('axis_x', true)
|
||
|
.attr('transform',"translate(0,"+translateY+")")
|
||
|
.attr("opacity",this.showScale?"1":"0")
|
||
|
//体温对应的Y轴坐标系
|
||
|
let temYEnd = this.topPadding + (5/(this.halveNum*2))*(this.height-this.bottomPadding-this.topPadding)
|
||
|
this.temYScale = d3.scaleLinear()
|
||
|
.domain([34,42])
|
||
|
.range([translateY+58,temYEnd+58]).clamp(true);
|
||
|
this.temYAxis = d3.axisRight().scale(this.temYScale).ticks(42-34);
|
||
|
console.log(""+temYEnd+","+translateY);
|
||
|
this.svg.append('g')
|
||
|
.call(this.temYAxis)
|
||
|
.classed('axis_x', true)
|
||
|
.attr('transform',"translate("+begin+",0)")
|
||
|
.attr("opacity","0")
|
||
|
//脉搏对应的Y轴坐标系
|
||
|
this.pulseYScale = d3.scaleLinear()
|
||
|
.domain([20,180])
|
||
|
.range([translateY+260,temYEnd+260]).clamp(true);
|
||
|
this.pulseYAxis = d3.axisRight().scale(this.pulseYScale).ticks(8);
|
||
|
this.svg.append('g')
|
||
|
.call(this.pulseYAxis)
|
||
|
.classed('axis_x', true)
|
||
|
.attr('transform',"translate("+begin+",0)")
|
||
|
.attr("opacity","0")
|
||
|
|
||
|
|
||
|
|
||
|
}
|
||
|
/***对外接口begin 所有外部绘制的点都要做标记class="outerData"*/
|
||
|
/**
|
||
|
*
|
||
|
* @param {腋表温度} ds
|
||
|
* @param {叉号有偏移量,是叉号的分支的一半长度} offset
|
||
|
*/
|
||
|
makeTempCrossLine(ds,offset){
|
||
|
let len = ds.length;
|
||
|
var resDs = [];
|
||
|
var physicalCool = [];
|
||
|
for(let i =0;i<len;i++){
|
||
|
//新数组,x坐标,y坐标,坐标上的值
|
||
|
if(ds[i].y!=""){
|
||
|
let newArr =[ds[i].x,ds[i].y];
|
||
|
resDs.push(newArr);
|
||
|
if(ds[i].y1!=undefined){//有物理降温
|
||
|
let pcArr =[ds[i].x,ds[i].y,ds[i].y1]
|
||
|
physicalCool.push(pcArr);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
let xSc = this.dateScale;
|
||
|
let ySc = this.temYScale;
|
||
|
resDs = resDs.map(d => [ xSc(d[0]+0.5), ySc(d[1]) ,d[1]] );
|
||
|
let svg = this.svg;
|
||
|
let tips = this.tips
|
||
|
let tipsText = this.tipsText;
|
||
|
let tipsRect = this.tipsRect;
|
||
|
let tems = svg.append("g")
|
||
|
.selectAll("bcuse").data(resDs).enter()
|
||
|
.append("use")
|
||
|
.attr("href","#T")
|
||
|
.attr("data-y",d =>d[2])
|
||
|
.attr("transform",d=>"translate("+(d[0]-offset)+","+(d[1]-offset)+") ")
|
||
|
.attr("opacity",d =>d[1]==undefined ? 0 : 1)
|
||
|
.classed("outerData",true)
|
||
|
.attr('cursor','pointer')
|
||
|
.on("mousemove",function(e){
|
||
|
// var pt = d3.pointer( e,tems.node() );
|
||
|
// console.log(pt,e.target.dataset.y);
|
||
|
tipsText.text ("体温:"+e.target.dataset.y +"℃") ;
|
||
|
tips.attr ('transform', 'translate(' + (e.pageX-10) + ',' + (e.pageY-50) + ')' )
|
||
|
tipsRect.attr("fill","rgb(111,111,111)")
|
||
|
tips.style('display', 'block');
|
||
|
})
|
||
|
.on ('mouseout' , function () {
|
||
|
tips.style('display', 'none');
|
||
|
})
|
||
|
var lnMaker = d3.line().defined((d,i) => d[1]==undefined ? false : true);
|
||
|
svg.append("g").append("path")
|
||
|
.attr("d",lnMaker(resDs))
|
||
|
.attr("fill","none")
|
||
|
.attr("stroke","blue")
|
||
|
.classed("outerData",true);
|
||
|
//绘制物理降温
|
||
|
if(physicalCool.length>0){
|
||
|
physicalCool.forEach((d)=>{
|
||
|
//绘制虚线
|
||
|
let pcResDs = [[xSc(d[0]+0.5),ySc(d[1])],[xSc(d[0]+0.5),ySc(d[2])]];
|
||
|
svg.append("g").append("path")
|
||
|
.attr("d",lnMaker(pcResDs))
|
||
|
.attr("fill","none")
|
||
|
.attr("stroke-dasharray","5,5")
|
||
|
.attr("stroke","red")
|
||
|
.classed("outerData",true);
|
||
|
//绘制红色圆圈
|
||
|
let rhcDs = [xSc(d[0]+0.5),ySc(d[2])];
|
||
|
svg.append("g")
|
||
|
// .selectAll("bcuse").data(rhcDs).enter()
|
||
|
.append("circle").attr("r",4)
|
||
|
.attr("cx",rhcDs[0]).attr("cy",rhcDs[1])
|
||
|
.style("fill","none")
|
||
|
.attr("stroke","red")
|
||
|
.classed("outerData",true)
|
||
|
});
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
/**
|
||
|
*
|
||
|
* @param {传入数据,42个 {"y":100,type:"P"}的数组} ds
|
||
|
*/
|
||
|
makePulseCrossLine(ds){
|
||
|
let len = ds.length;
|
||
|
var resDs = []
|
||
|
for(let i =0;i<len;i++){
|
||
|
//新数组,x坐标,y坐标,坐标上的值
|
||
|
if(ds[i].y!=""){
|
||
|
let newArr =[ds[i].x , ds[i].y , ds[i].type];
|
||
|
resDs.push(newArr);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
let xSc = this.dateScale;
|
||
|
let ySc = this.pulseYScale;
|
||
|
resDs = resDs.map(d => [ xSc(d[0]+0.5), ySc(d[1]), d[2] ,d[1]] );
|
||
|
let svg = this.svg;
|
||
|
|
||
|
let tips = this.tips
|
||
|
let tipsText = this.tipsText;
|
||
|
let tipsRect = this.tipsRect;
|
||
|
let tems = svg.append("g")
|
||
|
.selectAll("bcuse").data(resDs).enter()
|
||
|
.append("use")
|
||
|
.attr("href",d =>d[2])
|
||
|
.attr("data-y",d =>("#P"==d[2]?"P:":"HR:")+d[3])
|
||
|
.attr("transform",d=>"translate("+(d[0])+","+(d[1])+") ")
|
||
|
.attr("opacity",d =>d[1]==undefined ? 0 : 1)
|
||
|
.classed("outerData",true)
|
||
|
.on("mousemove",function(e){
|
||
|
// var pt = d3.pointer( e,tems.node() );
|
||
|
// console.log(pt,e.target.dataset.y);
|
||
|
tipsText.text (e.target.dataset.y) ;
|
||
|
tips.attr ('transform', 'translate(' + (e.pageX-10) + ',' + (e.pageY-50) + ')' )
|
||
|
tipsRect.attr("fill","rgb(128,0,128)")
|
||
|
tips.style('display', 'block');
|
||
|
|
||
|
})
|
||
|
.on ('mouseout' , function () {
|
||
|
tips.style('display', 'none');
|
||
|
})
|
||
|
var lnMaker = d3.line().defined((d,i) => d[1]==undefined ? false : true);;
|
||
|
svg.append("g").append("path")
|
||
|
.attr("d",lnMaker(resDs))
|
||
|
.attr("fill","none")
|
||
|
.attr("stroke","red")
|
||
|
.classed("outerData",true)
|
||
|
}
|
||
|
|
||
|
//设置患者的基本信息
|
||
|
setText(x,y,label,style){
|
||
|
let xScal = this.xScale;
|
||
|
let yScal = this.yScale;
|
||
|
let svg = this.svg;
|
||
|
svg.append("text")
|
||
|
.attr("x",xScal(x))
|
||
|
.attr("y",yScal(y))
|
||
|
.classed("outerData",true)
|
||
|
.classed(style,true)
|
||
|
.text(label);
|
||
|
}
|
||
|
/**
|
||
|
*
|
||
|
* @param {数组} ds
|
||
|
* @param {y轴的坐标} y
|
||
|
* @param {文本样式} style
|
||
|
*/
|
||
|
setTextData(ds,y,style){
|
||
|
let xScal = this.xScale;
|
||
|
let yScal = this.yScale;
|
||
|
if(ds){
|
||
|
let resDs = ds.map((d,i) => [ d.length >= 14 ? xScal(i+1): xScal((i + 1.45) - 0.45 / 13 * d.length), yScal(y-0.1), d] );
|
||
|
let svg = this.svg;
|
||
|
svg.append("g")
|
||
|
.selectAll("#id").data(resDs).enter()
|
||
|
.append("text")
|
||
|
.attr("x",d=>d[0])
|
||
|
.attr("y",d=>d[1])
|
||
|
.classed("outerData",true)
|
||
|
.classed(style,true)
|
||
|
.text(d=>d[2]);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
/**
|
||
|
*
|
||
|
* @param {[{"x":6,"value":"89","position":2},{"x":7,"value":"89","position":1}]} ds 呼吸记录
|
||
|
* @param {如果position =1,取y1} y1
|
||
|
* @param {如果position =2,取y2} y2
|
||
|
*/
|
||
|
setRrecord(ds,y1,y2,style){
|
||
|
let xScal = this.xScale;
|
||
|
let yScal = this.yScale;
|
||
|
let resDs = ds.map((d,i) => [ xScal((d.x+6)/6), d.position==1?yScal(y1):yScal(y2), d.value] );
|
||
|
let svg = this.svg;
|
||
|
svg.append("g")
|
||
|
.selectAll("#id").data(resDs).enter()
|
||
|
.append("text")
|
||
|
.attr("x",d=>d[0])
|
||
|
.attr("y",d=>d[1])
|
||
|
.classed("outerData",true)
|
||
|
.classed(style,true)
|
||
|
.text(d=>d[2]);
|
||
|
}
|
||
|
setBPrecord(ds,y1,y2,style){
|
||
|
let svg = this.svg;
|
||
|
let xScal = this.xScale;
|
||
|
let yScal = this.yScale;
|
||
|
var resDs = [];
|
||
|
let DLT ="▦";
|
||
|
if(ds){
|
||
|
for(let i =0;i<ds.length;i++){
|
||
|
let dsStr =ds[i].split(DLT)
|
||
|
if(dsStr.length==4){
|
||
|
resDs.push([ xScal((i*6+6)/6), yScal(y1), dsStr[0]]);
|
||
|
resDs.push([ xScal((i*6+6)/6),yScal(y2),dsStr[1]]);
|
||
|
resDs.push([ xScal((i*6+9)/6), yScal(y1), dsStr[2]]);
|
||
|
resDs.push([ xScal((i*6+9)/6),yScal(y2),dsStr[3]]);
|
||
|
}else if(dsStr.length==3){
|
||
|
resDs.push([ xScal((i*6+6)/6), yScal(y1), dsStr[0]]);
|
||
|
resDs.push([ xScal((i*6+6)/6),yScal(y2),dsStr[1]]);
|
||
|
resDs.push([ xScal((i*6+9)/6), yScal(y1), dsStr[2]]);
|
||
|
}else if(dsStr.length==2){
|
||
|
resDs.push([ xScal((i*6+6)/6), yScal(y1), dsStr[0]]);
|
||
|
resDs.push([ xScal((i*6+9)/6),yScal(y1),dsStr[1]]);
|
||
|
}else if(dsStr.length==1){
|
||
|
resDs.push([ xScal((i*6+6)/6), yScal(y1), dsStr[0]]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
svg.append("g")
|
||
|
.selectAll("#id").data(resDs).enter()
|
||
|
.append("text")
|
||
|
.attr("x",d=>d[0])
|
||
|
.attr("y",d=>d[1])
|
||
|
.classed("outerData",true)
|
||
|
.classed(style,true)
|
||
|
.text(d=>d[2]);
|
||
|
}
|
||
|
/**
|
||
|
*
|
||
|
* @param {*} ds
|
||
|
* @param {*} y1 文字从y轴哪个位置开始绘制
|
||
|
* @param {*} y2 竖线从y轴哪个位置开始绘制
|
||
|
* @param {*} style
|
||
|
*/
|
||
|
setEvent(ds,y1,y2,style){
|
||
|
let xSc = this.dateScale;
|
||
|
let ySc = this.temYScale;
|
||
|
let svg = this.svg;
|
||
|
if(ds){
|
||
|
let len = ds.length;
|
||
|
for(let i =0;i<len;i++){
|
||
|
let d = ds[i];
|
||
|
let x = d.x;
|
||
|
let ev = d.ev;//第一个事件
|
||
|
let evt = d.evt;//第一个事件的时间
|
||
|
let evLen = ev.length;
|
||
|
let evtLen = evt.length;
|
||
|
|
||
|
let resDs = [];
|
||
|
let count =0
|
||
|
for(let m =0;m<evLen;m++){
|
||
|
resDs.push([x,count,ev[m]]);
|
||
|
count++;
|
||
|
}
|
||
|
// count +=2;
|
||
|
for(let m =0;m<evtLen;m++){
|
||
|
resDs.push([x,count,evt[m]]);
|
||
|
count++;
|
||
|
}
|
||
|
|
||
|
svg.append("g")
|
||
|
.selectAll("#id").data(resDs).enter()
|
||
|
.append("text")
|
||
|
.attr("x",d1=> this.isNumber(d1[2])?xSc(d1[0]+0.2):xSc(d1[0]))
|
||
|
.attr("y",d1=>ySc(y1-(d1[1]+1)/3.8))
|
||
|
.classed("outerData",true)
|
||
|
.classed(style,true)
|
||
|
.attr("fill","red")
|
||
|
.text(d1=>d1[2]);
|
||
|
console.log(ds[i]);
|
||
|
// if(evtLen>0){
|
||
|
// svg.append("line")
|
||
|
// .attr("x1",xSc(x+0.5))
|
||
|
// .attr("y1",ySc(y2-(evLen)/5))
|
||
|
// .attr("x2",xSc(x+0.5))
|
||
|
// .attr("y2",ySc(y2-(evLen+2)/3.5))
|
||
|
// .attr("style","stroke:rgb(255,0,0);stroke-width:1")
|
||
|
// .classed("outerData",true);
|
||
|
// }
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
/**
|
||
|
*
|
||
|
* @param {*} ds
|
||
|
* 房颤
|
||
|
*/
|
||
|
setPHrecord(ds){
|
||
|
let svg = this.svg;
|
||
|
let xSc = this.dateScale;
|
||
|
let ySc = this.pulseYScale;
|
||
|
if(ds){
|
||
|
for(let i =0 ;i<ds.length;i++){
|
||
|
this.makeLine(svg,
|
||
|
xSc,
|
||
|
ySc,
|
||
|
ds[i].x,ds[i].y,
|
||
|
ds[i].x1,ds[i].y1
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
setAllergyMedical(ds,y,style,fs){
|
||
|
let xScal = this.xScale;
|
||
|
let yScal = this.yScale;
|
||
|
let svg = this.svg;
|
||
|
if(ds){
|
||
|
let len = ds.length;
|
||
|
for(let i=0;i<len;i++){
|
||
|
if(""!=ds[i]){
|
||
|
let textSpan = svg.append("g")
|
||
|
.append("text")
|
||
|
.attr("x",xScal(i+1))
|
||
|
.attr("y",yScal(y-0.5))
|
||
|
.classed("outerData",true)
|
||
|
.text("");
|
||
|
let amArr = ds[i].split("、");
|
||
|
amArr.forEach((am,index)=>{
|
||
|
if(am.indexOf("+")>-1){//如果是阳性
|
||
|
let amiArr = am.split("");
|
||
|
for(let m =0;m<amiArr.length;m++){
|
||
|
let ami = amiArr[m];
|
||
|
//如果前一个字符不是中文的,x的偏移量是12
|
||
|
let offX=fs||14;
|
||
|
if(m>0){
|
||
|
if(escape(amiArr[m-1]).indexOf( "%u" )<0){
|
||
|
offX = 13.5;
|
||
|
}
|
||
|
}
|
||
|
textSpan.append("tspan").text(ami)
|
||
|
.attr("x",xScal(i+1)+m*(offX))
|
||
|
.attr("y",yScal(y-0.5)+(index==0?3:fs||14))
|
||
|
.attr("style",ami=="+"?"fill:red;":"fill:blue;")
|
||
|
.classed(style,true)
|
||
|
.classed("outerData",true)
|
||
|
}
|
||
|
|
||
|
|
||
|
}else{
|
||
|
textSpan.append("tspan").text(am)
|
||
|
.attr("x",xScal(i+1))
|
||
|
.attr("dy",index==0?3:fs||14)
|
||
|
.attr("style","fill:red;")
|
||
|
.classed(style,true)
|
||
|
.classed("outerData",true)
|
||
|
}
|
||
|
});
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
removeOuterData(){
|
||
|
let svg = this.svg;
|
||
|
svg.selectAll(".outerData").remove();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/**对外接口end */
|
||
|
}
|
||
|
|