我们有许多众所周知的图表类型:酒吧,甜甜圈,线,派,您可以命名。所有流行的图表库支持这些。然后有图表类型甚至没有名称。使用堆叠的(嵌套)正方形查看此DreamT-Up图表,可以帮助可视化相对大小,或者不同的值相互比较:
没有任何互动,创建此设计非常简单。一种方法是堆叠元素(例如SVG
但是,一旦我们引入了一些互动性,事情就会变得棘手。应该这样做:当我们将鼠标移到其中一种形状上时,我们希望其他人逐渐消失并移开。
我们将使用矩形和掩码创建这些不规则的形状 - 具有
现在,在我们开始之前,您可能会想知道是否是使用自定义形状的更好的SVG替代品。绝对是可能的!但是用绘制形状可能令人生畏,甚至会变得凌乱。因此,我们正在使用“更容易”的元素来获得相同的形状和效果。
例如,这是我们必须使用
<svg viewbox="“" width="“" height="“"> </svg>
如果0H0V56…对您没有任何意义,请查看“ SVG路径语法:插图指南”,以详细说明语法。
给定这样的数据集:
键入datasetEntry = { 标签:字符串; 值:数字; }; 键入dataset = datasetEntry []; const rawdataset:dataset = [ {label:'bad',值:1231}, {label:'begint',value:6321}, {label:'开发',值:10028}, {label:'已完成',值:12123},, {label:'示例',值:2120} ];
…我们想以这样的SVG结束:
<svg viewbox="“" width="“" height="“"> <rect width="“" height="“" y="“" fill="“" ...> </rect> <rect width="“" height="“" y="“" fill="“" ...> </rect> <rect width="“" y="“" fill="“" ...> </rect> <rect width="“" y="“" fill="“" ...> </rect> <rect width="“" height="“" y="“" fill="“" ...> </rect> </svg>
在瞬间,我们需要最高价值会变得很明显。我们可以使用Math.max()获取它。它接受任何数量的参数,并返回集合中的最高值。
const dataseThighestValue:number = math.max( ... RAWDATASET.MAP((输入:DataSetEntry)=> entry.value) );
由于我们有一个小数据集,因此我们可以说我们将获得12123。
如果我们看设计,则代表最高值(12123)的矩形覆盖了图表的整个区域。
我们任意选择320个SVG尺寸。由于我们的矩形是正方形,因此宽度和高度相等。我们如何使12123等于320?较少的“特殊”值怎么样? 6321矩形有多大?
换句话说,我们如何将一个数字从一个范围([0,12123])映射到另一个范围([0,320])?或者,用更多的数学术语,我们如何将变量扩展到[a,b]的间隔?
出于我们的目的,我们将实现这样的功能:
const remapvalue =( 价值:数字, Frommin:数字, Frommax:数字, Tomin:数字, tomax:数字 ):数字=> { 返回((value -frommin) /(frommax -frommin)) *(tomax -tomin)tomin; }; 重新值(1231,0,12123,0,320); // 32 重新值(6321,0,12123,0,320); // 167 重新值(12123,0,12123,0,320); // 320
由于我们将值映射到代码中的相同范围,而不是一遍又一遍地传递最小值和最大值,因此我们可以创建一个包装函数:
const valuerMapper =( Frommin:数字, Frommax:数字, Tomin:数字, tomax:数字 )=> { 返回(值:数字):number => { 返回重新值(Value,Frommin,Frommax,Tomin,Tomax); }; }; const remapdatasetValuetosvgdimension = valueremapper( 0, DataseThighestValue, 0, svgdimension );
我们可以这样使用:
RemapdatasetValuetosvgdimension(1231); // 32 RemapdatasetValuetosvgdimension(6321); // 167 RemapdatasetValuetosvgdimension(12123); // 320
剩下的与DOM操纵有关。我们必须创建
请注意,我们使用的是CreateElementn,而不是更常见的Createlement。这是因为我们正在使用SVG。 HTML和SVG元素具有不同的规格,因此它们属于不同的名称空间URI。碰巧的是,CreateElement便利地使用HTML名称空间!因此,要创建一个SVG,我们必须是这个冗长:
document.createelementns('http://www.w3.org/2000/svg','svg')as svgsvgelement;
当然,我们可以创建另一个辅助功能:
const createsvgnSelement =(element:string):svgelement => { 返回document.createelementns('http://www.w3.org/2000/svg',element); };
当我们将矩形附加到DOM时,我们必须注意它们的命令。否则,我们必须明确指定z索引。第一个矩形必须是最大的,最后一个矩形必须是最小的。最好在循环之前对数据进行分类。
const data = rawdataset.sort( (a:datasetEntry,b:datasetEntry)=> b.value -a.value ); data.foreach((D:DATASETENTRY,index:number)=> { const rect:svgrectelement = keresvgnSelement('rect')作为svgrectelement; const rectdimension:number = remapdatasetValuetosvgdimension(d.Value); rect.setAttribute('width',`$ {rectDimension}`); rect.setAttribute('height',`$ {rectDimension}`); rect.setAttribute('y',`$ {svgdimension -rectDimension}`); svg.appendchild(rect); });
坐标系从左上角开始;那就是[0,0]在哪里。我们总是要从左侧绘制矩形。控制水平位置的X属性默认为0,因此我们不必设置它。 Y属性控制垂直位置。
为了给人以视觉印象:所有矩形都源于触摸其左下角的同一点,我们必须将矩形向下推下。多少钱?矩形不填充的确切量。该值是图表的维度和特定矩形之间的差异。如果我们将所有位放在一起,我们最终都会得到这样做:
我们已经使用CSS添加了该动画的代码。
我们必须将矩形变成不规则的形状,看起来像是第七名,或者字母L旋转180度。
如果我们专注于“丢失的零件”,那么我们可以看到它们切入了我们已经与之合作的相同矩形。
我们想隐藏那些切口。这就是我们最终要获得想要的L形状的方式。
掩模是您定义的东西,然后应用于元素。通常,掩码在其属于的
<svg> <mask> </mask> </svg>
在
<svg> <mask> </mask> <rect mask="“" url> </rect> </svg>
这不是定义或涂上口罩的唯一方法,但这是该演示的最直接方法。让我们在编写任何代码以生成口罩之前进行一些实验。
我们说,我们想覆盖与现有矩形大小相匹配的切口区域。如果我们采用最大的元素,并且将先前的矩形应用于掩模,我们最终以此代码:
<svg viewbox="“" width="“" height="“"> <mask> <rect width="“" height="“" y="“" fill="“”"> </rect> </mask> <rect width="“" height="“" y="“" fill="“#264653”" mask="“" url> </rect> </svg>
蒙版内的元素需要一个填充值。那应该是什么?我们会根据选择的填充值(颜色)看到完全不同的结果。
如果我们为填充使用白色值,那么我们就会得到:
现在,我们的大矩形与掩蔽矩形相同。不完全是我们想要的。
如果我们使用黑色值,则看起来像这样:
我们什么都没有。那是因为充满黑色的东西变得不可见。我们使用白色和黑色填充物控制面具的可见性。虚线作为视觉辅助,以引用无形区域的尺寸。
现在,让我们使用白色和黑色之间的东西,说格雷:
它既不是完全不透明的也不是坚固的;这是透明的。因此,现在我们知道我们可以使用与白色和黑色值不同的东西来控制这里的“可见度”,这是一个很好的技巧,可以保留在我们的后口袋中。
到目前为止,这是我们涵盖和了解的有关面具的知识:
我们只为掩模使用了一种形状,但是与任何通用HTML标签一样,我们可以根据需要在其中嵌套尽可能多的子元素。实际上,实现我们想要的目标的诀窍是使用两个SVG
<svg viewbox="“" width="“" height="“"> <mask> <rect width="“" height="“" y="“" fill="“"> </rect> <rect width="“" height="“" y="“" fill="“"> </rect> </mask> <rect width="“" height="“" y="“" fill="“#264653”" mask="“" url> </rect> </svg>
我们的掩蔽矩形之一充满了白色。另一个充满黑色。即使我们知道规则,也要尝试一下可能性。
<mask> <rect width="“" height="“" y="“" fill="“" black> </rect> <rect width="“" height="“" y="“" fill="“" white> </rect> </mask>
现在让我们对黑色矩形顶部的东西进行翻转:
<mask> <rect width="“" height="“" y="“" fill="“" white> </rect> <rect width="“" height="“" y="“" fill="“" black> </rect> </mask>
这就是我们想要的!
最大的白色矩形下的所有内容都是可见的,但是较小的黑色矩形在其顶部(在Z轴上更靠近我们),掩盖了这一部分。
现在我们知道了我们必须做什么,我们可以相对轻松地创建口罩。这类似于我们首先生成彩色矩形的方式 - 我们创建了一个辅助环,在其中创建掩码和两个矩形。
这次,我们没有将矩形直接附加到SVG上,而是将其附加到蒙版:
data.foreach((D:DATASETENTRY,index:number)=> { constmask:svgMaskElement = svgmaskelement; createSvgnSelement('mask'); const rectdimension:number = remapdatasetValuetosvgdimension(d.Value); const rect:svgrectelement = keresvgnSelement('rect')作为svgrectelement; rect.setAttribute('width',`$ {rectDimension}`); // ...设置其余属性... mask.setAttribute('id',`maskw $ {rectDimension.tofixed()}`); mask.appendchild(rect); // ...创建和设置较小矩形的属性... svg.appendchild(蒙版); }); data.foreach((D:DATASETENTRY,index:number)=> { // ...我们的代码生成彩色矩形... });
我们可以将索引用作面具的ID,但这似乎是一个更可读的选择,至少对我而言:
mask.setAttribute('id',`maskw $ {rectDimension.tofixed()}`); // MaskW320,MASW240,...
至于在面罩中添加较小的矩形,我们可以轻松访问所需的值,因为我们以前订购了从最高到最低的矩形值。这意味着循环中的下一个元素是较小的矩形,我们应该引用一个元素。我们可以通过其索引来做到这一点。
// ...上一部分我们创建了蒙版和矩形... const smalleRectIndex =索引1; //当我们处于最小时,没有下一个 if(data [smalleRectIndex]!== undefined){ const smalleRectDimension:number = remapdatasetValuetosvgdimension( 数据[SmalleRectIndex] ); const smallErcret:svgrectelement = createSvgnSelement( 'rect' )作为svgrectement; // ...设置矩形属性... mask.AppendChild(SmallerRect); } svg.appendchild(蒙版);
剩下的就是将蒙版属性添加到我们原始循环中的彩色矩形中。它应该匹配我们选择的格式:
rect.setAttribute('mask',`url(#baskw $ {rectdimension.tofixed()})`); // maskW320,maskW240,...
我们完成了!我们已经成功制作了一个由嵌套正方形制成的图表。它甚至在鼠标悬停上分开。而所需的只是使用
以上是如何使用口罩创建嵌套正方形的动画图表的详细内容。更多信息请关注PHP中文网其他相关文章!