From 62636acc272eccd789afc37f7a68ced4d55fa931 Mon Sep 17 00:00:00 2001 From: Pomax Date: Mon, 10 Aug 2020 22:30:45 -0700 Subject: [PATCH] bug fix on the event cancellation, which was causing scroll jumps and input-change cancellation --- chapters/control/content.en-GB.md | 2 +- chapters/control/content.ja-JP.md | 2 +- chapters/control/content.zh-CN.md | 2 +- chapters/weightcontrol/content.en-GB.md | 26 ++--- chapters/weightcontrol/rational.js | 30 ++++++ .../8d7391688575c8c588ea741ada7b893e.png | Bin 8807 -> 8903 bytes .../c0aa6126567320c80a3039a47edf994a.png | Bin 10072 -> 10124 bytes .../1128afb7511e00ad4c5e8c0628204b56.png | Bin 0 -> 10124 bytes .../3fd61ab3fe88f694e70f61e4f8ea056b.svg | 1 + .../fe880741c0d91317587412f1badeab3f.svg | 1 + index.html | 78 +++++++++------ ja-JP/index.html | 74 ++++++++------ lib/custom-element/api/base-api.js | 25 +++-- lib/custom-element/api/graphics-api.js | 2 + lib/custom-element/api/types/bezier.js | 12 +-- package-lock.json | 91 ++++++++++++++++++ package.json | 5 +- tools/build/create-index-page.js | 5 + .../markdown/preprocess-graphics-element.js | 8 +- tools/build/process-locale.js | 5 + zh-CN/index.html | 74 ++++++++------ 21 files changed, 314 insertions(+), 129 deletions(-) create mode 100644 chapters/weightcontrol/rational.js create mode 100644 images/chapters/weightcontrol/1128afb7511e00ad4c5e8c0628204b56.png create mode 100644 images/latex/3fd61ab3fe88f694e70f61e4f8ea056b.svg create mode 100644 images/latex/fe880741c0d91317587412f1badeab3f.svg diff --git a/chapters/control/content.en-GB.md b/chapters/control/content.en-GB.md index 6b9b2d3d..7e4425b9 100644 --- a/chapters/control/content.en-GB.md +++ b/chapters/control/content.en-GB.md @@ -2,7 +2,7 @@ Bézier curves are, like all "splines", interpolation functions. This means that they take a set of points, and generate values somewhere "between" those points. (One of the consequences of this is that you'll never be able to generate a point that lies outside the outline for the control points, commonly called the "hull" for the curve. Useful information!). In fact, we can visualize how each point contributes to the value generated by the function, so we can see which points are important, where, in the curve. -The following graphs show the interpolation functions for quadratic and cubic curves, with "S" being the strength of a point's contribution to the total sum of the Bézier function. Click or click-drag to see the interpolation percentages for each curve-defining point at a specific t value. +The following graphs show the interpolation functions for quadratic and cubic curves, with "S" being the strength of a point's contribution to the total sum of the Bézier function. Click-and-drag to see the interpolation percentages for each curve-defining point at a specific t value.
diff --git a/chapters/control/content.ja-JP.md b/chapters/control/content.ja-JP.md index f02cb05c..82447736 100644 --- a/chapters/control/content.ja-JP.md +++ b/chapters/control/content.ja-JP.md @@ -2,7 +2,7 @@ ベジエ曲線は(すべての「スプライン」と同様に)補間関数です。これは点の集合を受け取って、それらの点のどこか「内側」の値を生成するということです。(このことから、制御点同士を結んで輪郭をつくったとき、その外側に位置する点は決して生成されないことがわかります。なお、この輪郭を曲線の「包」と呼びます。お役立ち情報でした!)実際に、補間関数によって生成された値に対する、各点の寄与の大きさを可視化することができますが、これを見れば、ベジエ曲線のどの場所でどの点が重要になるのかがわかります。 -下のグラフは、2次ベジエ曲線や3次ベジエ曲線の補間関数を表しています。ここでSは、ベジエ関数全体に対しての、その点の寄与の大きさを示します。あるtにおいて、ベジエ曲線を定義する各点の補間率がどのようになっているのか、クリックやドラッグをして確かめてみてください。 +下のグラフは、2次ベジエ曲線や3次ベジエ曲線の補間関数を表しています。ここでSは、ベジエ関数全体に対しての、その点の寄与の大きさを示します。あるtにおいて、ベジエ曲線を定義する各点の補間率がどのようになっているのか、クリックドラッグをして確かめてみてください。
diff --git a/chapters/control/content.zh-CN.md b/chapters/control/content.zh-CN.md index cdc8e54e..cc51ae43 100644 --- a/chapters/control/content.zh-CN.md +++ b/chapters/control/content.zh-CN.md @@ -2,7 +2,7 @@ 贝塞尔曲线是插值方程(就像所有曲线一样),这表示它们取一系列的点,生成一些处于这些点之间的值。(一个推论就是你永远无法生成一个位于这些控制点轮廓线外面的点,更普遍是称为曲线的外壳。这信息很有用!)实际上,我们可以将每个点对方程产生的曲线做出的贡献进行可视化,因此可以看出曲线上哪些点是重要的,它们处于什么位置。 -下面的图形显示了二次曲线和三次曲线的差值方程,“S”代表了点对贝塞尔方程总和的贡献。点击或拖动点来看看在特定的t值时,每个曲线定义的点的插值百分比。 +下面的图形显示了二次曲线和三次曲线的差值方程,“S”代表了点对贝塞尔方程总和的贡献。点击拖动点来看看在特定的t值时,每个曲线定义的点的插值百分比。
diff --git a/chapters/weightcontrol/content.en-GB.md b/chapters/weightcontrol/content.en-GB.md index 73232e8c..0b0c494d 100644 --- a/chapters/weightcontrol/content.en-GB.md +++ b/chapters/weightcontrol/content.en-GB.md @@ -11,27 +11,21 @@ Adding these ratio values to the regular Bézier curve function is fairly easy. The function for rational Bézier curves has two more terms: \[ - Rational\ Bézier(n,t) = \left ( \sum_{i=0}^{n} \binom{n}{i} \cdot (1-t)^{n-i} \cdot t^{i} \cdot w_i \cdot BLUE[ratio_i] \right ) \cdot BLUE[\frac{ 1 }{ Basis_{(n,t)} }] + Rational\ Bézier(n,t) = \frac{ \sum_{i=0}^{n} \binom{n}{i} \cdot (1-t)^{n-i} \cdot t^{i} \cdot w_i \cdot BLUE[ratio_i] }{ BLUE[ \sum_{i=0}^{n} \binom{n}{i} \cdot (1-t)^{n-i} \cdot t^{i} \cdot ratio_i ] } \] -In this, the first new term represents the ratio for each coordinate, as a multiplication factor. If our ratio values are [1, 0.5, 0.5, 1] then ratio0 = 1, ratio1 = 0.5, and so on. The second term then corrects for all those multiplications by dividing the total value by the "basis" value of the Bézier curve, i.e. the value we get by computing the curve without any weighting at (but _with_ ratios): +In this, the first new term represents the ratio for each coordinate, as a multiplication factor. If our ratio values are [1, 0.5, 0.5, 1] then ratio0 = 1, ratio1 = 0.5, and so on. The second term then corrects for all those multiplications by dividing the total value by the "basis" value of the Bézier curve, i.e. the value we get by computing the curve without any weighting (but _with_ ratios): -\[ - Basis_{n,t} = \sum_{i=0}^{n} \binom{n}{i} \cdot (1-t)^{n-i} \cdot t^{i} \cdot ratio_i -\] +So what does this actually do? Let's look at the effect of "rationalising" our Bézier curves by interacting with the curve and ratios. The following graphic shows the curve from the previous section, enriched with ratio factors: the closer to zero we set one or more terms, the less relative influence the associated coordinate exerts on the curve (and of course the higher we set them, the more influence they have). -So what does this actually do? + + ratio 1 1.0
+ ratio 2 1.0
+ ratio 3 1.0
+ ratio 4 1.0 +
-Let's look at the effect of "rationalising" our Bézier curves by interacting with the curve and ratios. The following graphic shows the curve from the previous section, enriched with ratio factors: the closer to zero we set one or more terms, the less relative influence the associated coordinates exert on the curve (and of course the higher we set them, the more influence they have). - - - - You can think of the ratio values as each coordinate's "gravity": the higher the gravity, the closer to that coordinate the curve will want to be. You'll also notice that if you simply increase or decrease all the ratios by the same amount, nothing changes... much like with gravity, if the relative strengths stay the same, nothing really changes. The values define each coordinate's influence _relative to all other points_. +You can think of the ratio values as each coordinate's "gravity": the higher the gravity, the closer to that coordinate the curve will want to be. You'll also notice that if you simply increase or decrease all the ratios by the same amount, nothing changes... much like with gravity, if the relative strengths stay the same, nothing really changes. The values define each coordinate's influence _relative to all other points_.
diff --git a/chapters/weightcontrol/rational.js b/chapters/weightcontrol/rational.js new file mode 100644 index 00000000..94f3c35d --- /dev/null +++ b/chapters/weightcontrol/rational.js @@ -0,0 +1,30 @@ +setup() { + this.curve = Bezier.defaultCubic(this); + setMovable(this.curve.points); + + const inputs = findAll(`input[type=range]`); + if (inputs) { + const ratios = inputs.map(i => parseFloat(i.value)); + this.curve.setRatios(ratios); + inputs.forEach((input,pos) => { + input.listen([`input`], evt => { + evt.target.nextSibling.textContent = ratios[pos] = parseFloat(evt.target.value); + this.curve.update(); + this.redraw(); + }); + }) + } + } + + draw() { + clear(); + const curve = this.curve; + curve.drawSkeleton(); + curve.drawCurve(); + curve.drawPoints(); + } + + onMouseMove() { + this.curve.update(); + redraw(); + } diff --git a/images/chapters/introduction/8d7391688575c8c588ea741ada7b893e.png b/images/chapters/introduction/8d7391688575c8c588ea741ada7b893e.png index 3aecf69ecfa2ba4db60de3bf9f6751677909d6d3..91c110ecd86bf79a92615895bd1b7236b00d408f 100644 GIT binary patch literal 8903 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 NFiIMV1!(gp{{_lR?{)wH literal 8807 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 cw8JUz@BVv>L+@7MiW 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 literal 10072 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 diff --git a/images/chapters/weightcontrol/1128afb7511e00ad4c5e8c0628204b56.png b/images/chapters/weightcontrol/1128afb7511e00ad4c5e8c0628204b56.png new file mode 100644 index 0000000000000000000000000000000000000000..51fb9cc2181d674401f7599628219804f8f73018 GIT binary patch literal 10124 zcmb_?byQbf6y*;U=~g7AL%Kw1MY@qtkWT58E~S<3MnXX;DW#E6L`pzFLTN-A>7MiW zzHesMtTk)RAG2I6F38&c)Q{iCMH98xKW_A zT7*HQK_r=Dv?sz?H<(|I(d*exlV;4t$rnlFgKBEi0ck! zzmQxCCS9>)s}!d3RbpmI%%T_`BFTrrLE(h0Y>Y}lgxYk*^g-{iu}J8GwEjQdnxkHi zq7$ai>zA{zU>+SE)ob>nM%}t~3-|KHmX?;s)w+r7w*L5k3AyOf3aY9S#JqRa3=9m` zoikNrH8rnzH8y3kYb3)YdyE7qMjJf&uU@_C;hoLGVT(Z^8iRhv&(CmRfLTq==%x4G zno_3lP^m8KfF->YznPiYF&U$dl&pVP*}9bg1p`GSk>TWEd%I8A2X|8F1#T$Rx37=m zA<8A^(yKw;@z}@D$Y5LMaCa>>`}UH$dbs);tdqb!Wy_-E2X2AO9^UE6iHV8TipuX{ z6~inX9UW0G%d=#pogNoh+rB{N_$^PC0ELZnky5X~LZ_#0_xwIgTmg(vo3kWu-o6!4 zDtfEX25svSZ|?Zc_I&yHvC=Q3Y^n>#z^ zt7FwD4{z`I#6)Rzb@dlfkrDhvxv8ZFjbF3Gylb3hWg5Hm_4UJ_KhL%7%i7_J4i7h; zZVkqz7EWjjC8)F;7hLF04Xm#h+4|jAkemAqk5cgAu)Cw<)LPk}?6YIb(>?#QV)frl+T2TX_7AJx&k${B!#sd#sdq$SEjDs$Y?b zq>xrnz<&DlX~Ws+QB6$^kHfD93z}XW%6ez?dGf=3w=A5TIN8M5}Xes*c;Ym@I$Sa|q!tnBq1|FcsmS=ma5NpaNi z$%&BL%EK2?FS>h(a?z`FIdgJyME9oxBgl9!lxQnDJ3Gg}Z}i$>%gV}nVj$tO&jUMT zes+2iX>X{f7m=KtJn!z{;PCwUb4+aPx0P$N(GtB+FJd@4JDUu>)!N_RSG#}z{`xKo z9#2S068z&bp{UC&S@o>b?83*+&NrRoi#vzHC&bIcC8n^Iwm<8x8X8W@eAwIAc=_(# zx4+(Z@7`^kz7&&?5Y%Zl^CgynL$@mI#Wn7kwKap~ll5Osg@s`Tjb1koDkqd7uC;k6 zB2kY8lpW>>u8XE*WKebOIypHN>sCJx#2_FhCU%}&?T8?6OS@^qdgF$1R}v?R3^zo0 zx$$5j-RJCNPg6?^O-)Bf-rSriPd3`3BZ@jh+&4|5K&9Mfgi9v+I^G=>6@1ud?5Zde=X3#H6IJBd&|pb&eMsHXF#x$*EnDR*#E|yYh0l@8#V<_+zQTVC%_Eibw@L zy^MiMOI4=Zw;#%@sA$7~&CJdw?(cha9p%4%&2}#YSG~?{^{wdfM%&lAC(9gN+GPeM z+iO1`{rOq{p~9kvqH7tZr43u6>&lVe2d`Ubl`8OCz;dk0N-0Z}JRp`qcDU}o%ZCsH zcQ-eSou#2-gT}i4JuDm?n~e%5Jv}N|jB10fzCIROT9kxD^O0|mSLZ8ZI^F4&(aP== z-izGa+-~c?O5B9r#)*^A>E^t?xciIu`mS750AY#a?_TPUK1;^y0Jx8XAAPV#BW9*G zrk5(3Xz(QYSZd$*gAnjn_pUCpL@eOaRr|>%Jh_wrfR++^&iHJA<$i2{u7K^-^K19F zXiK^D>k9S456?SHqhzeDsrg@j^28>EpFeB-m*l)(6&F8x7>@nB>qmtYq&Kz)Wd`Uk zZAMDj9^{H6w-h!sP{nr!X&2cI+fj^dHBj>CRw8>j9>7!8w`!Xa6jnS1(vGQ8 zvW|y|2Ip^83!dM*aQES!cSb=YB$wRa=PzEM{d=cc4}&0+Qa3V9I;+(0%rFZa`ILWt zYieuXhjWmZmlxC-jok6HwN>(MQPJl1c0$3yiCok(LQco|uUAoiyOr5*^ukw>&e0i_ zmJsazpTGZZZJ~KgJ;l&0ZFfUn?LuvBEo%Sp@a=yOShu$K^{LJ)*oGod?RvCp2lMN< zt_Hj-(vRvvI!$$UaZ$g5ZfIyoZt8qZh*(k}emnWQDuVWPj?))Vr>Cb&q$Z}w9AB@j z*rG06yr@;${vH`l>33f?2BXp%6TBI}=7R?=n={gPTIUQ9L~l!Ee^BFlBnXMErmpU- zev~q@yW|xW6)3C3@3Khuw_O%+Q74Bx8nwjZ3`iHpN0Volr&=&*H2=Huy-Ml2*CHM4 zgBa3je^2_Y&aSR|MMDDxsx;MI#Ssk+qI!CIJY=}m$)@qh%RcMw zR=OgcW7zC>TS({)%pd6mtLg028zp(~9xQ>IJS@Sbv%`^Ql*e|z?7vr>XaI{dL_LWy zFfcCTlD%{j5>$kjJ-Y3^%kjZs^0jKV_~MQiOkD@2J|U~COF?_WvWdnApp~-h)qkw{&GV_ z1KE-=2H7YSArVoIGt+xy4==;*jx+6885tRv1OyLYby#3^E=FA!QvkGz7C&Sa&Qw`- zw#|b0z$+B`6dn{|GB$Q2hR@O^gs&)^kO(wX^rCih$i zdKi7lX=CaxN+yabJTNfuzuWSdm1H8wU=Gws-0ju)9Ps__&AeAIxcS2HSaQ`_7#E&g zD@PIul5Z+2E8$5hWI-5sd5HpeO+Odv$#=l9ZP)+%_wW96D9z$gO@ttcJfDKTpV#+e7uvJTareGHk=?ghojw9IM07+&NgYbmxdJK{W!2lj7Q$Sefy*C z2|G$vY$pMRuq9@0Eu|Lqh&ev?f%G|#zg@y;OusS)j0WX#_@}_hHKFXD&6j=>H+FXR z7gbdPfaNl-u2p06t{(8HeTiZ7b!qjmsHoRK`>c}(ry>68VSC$wrZ~E~nthHShpRUr z3hJwXwJ0%@0P24p8F>KnL5KOcf9>kxOb)c{&3NN{GZQxEoe1SE`?=4Nlu}Ysgj7_; zZbF$MaFzXo{ZEtG&ygt6y$Kh#2ZOapj}=yf%%%GEpFcjmIL}L}4Oq4!XSG_mQWm-BqXz}iVD8V_*AU-evboUzrz_R)t~L+ZoXu+yD|#h2_e(o7`4oH+FDQ! zA)w*%WwMiMm2&mE#%*8*sr9z7@ZY~(+(r5-1%NBUjnNXPDPO-TWO*&!INV)@{mx7Z z3SaylMJ@8#ebQGJChM{J>Dmxifd-tJOl^p2=;Y$mhvt)#iMaAe`IIn~Wf-1OM1)d8 zLL!xX0$;%T8g1I=#{zMwsq$`af+J;y7$19j@B&*9cn~!^x{i*HUi|0-KEl?%Y+7Lu zGgIHOvby2DyOPt;&@jBr#KZ)=((!QHDmORx+wu;Z)?;r{Zi8+BCvq__0VE&SQ`OTN zo6JVYF!-MxO};5C{CITi+3L13^|Y7+_4jC($*%PhHtuCenmym&Xv}l-ymMbSIOl(Z ze>_fhMuxaL?B%kd*S*_I4>G4t;z?@$vDklg%D5D%tAw zT$8jiqn2(G04%65>m)`Qc(2~{@$u0t{c7@ojPA3#g}fm!dk& zOa}7h?H<@thDAocs;jG$Uq;r5nUfQbfPg@#Q9U*&JhBsL2^Uw?&^H(NEQB|xRX^kV?p&YH{MYvrJjkPD7eAJM3& zs6g3FZFbO;r@!>9h%U&utaHxxyagFxYe(s4G{Q2{zSihcBR#x_x@18!nO&&eDr3nKzHul3x z3p@y=7Bjx-xw-a1Rf(RhJ_%I_TO_`CXaky?53Mup{!tvQqocLId>tlgVuNw6UEpz^ zle;244M(tHt5>9YSmTOIUw5N%g>lOD5;*|m$OMw(A=*1N5?n(^@(eMFr?=HqktC90>d-@m-m{`oU85z*7o zPz;L5%aJmH&>$irQcC3u26z(Ozb+en{nO-R^QW84%*@2su7!eNDlacbWk~op=^Q<5 z@)6Rnb48MElJT03jt-<;B1*~^&HsXLol#(EFJg6Hq0L5ycR%Q{3DznnBiM)YFb*KS^_aV0W}T|m&?dS+z?6W z1AhX+j^CW^*h+3bex>~ElF`Og%iP>tmB$g}*LNTb6ciMGRG8zSE(hj}9)VJ)7Zc00 z8-LI1ICTe*RuSUm(R#547>=3I!QFPFNrm` zXQIjX5eOoOgwaY%_U5yb^~CSrHNlQC|MdK-!o!Ct#MiHv9?x_8TWtvsml>8ZGBUD0 z&t;XDm&abm#hk=f$Y*a6Ln8s|XFJOyvnwmz_3KSG2Z|F(aO~q*R4sttX#aHR8A|mo8+h0T zCdZEk&&qjhEk8f;=7SywRyH=1i5jPdyIZDQJwCN?`#a;dhZSb>nZ0f6O-E6x5+_#>Ao5-p!-`{OCta<~cPYD_aG41`uy>!%mjMr&PI5Kc=5aRg`n;~pzF zx8?UjbR#^+( z%FW%ipIs2hfHDmbV5^#T9opL3pCPGtztJez*xWP*3+G(XB-IdL#UB;EeLDjO$#$}d zI#Q-BURAtvW4bL}V5Xw3E)6Dgfd?p%OlSj6B``VgZV;x})YJr;Hx1*u$DP#*DH6F9 zfvMh1k(Kce(fajn(`#$JWqv#Cu-a+W(Xb1M&hgq?>j|Q9Afcs5ijQxD_h_B(O6DcQ z^#LYVl6IMPEIFuCY>k?M&wWj=i!65GZK@;)`otilSeAV-JrhARcZ~V3pyjcSO z{d;-TW37Utz9|Cc5ps%i3k%M(pYg7HOrh1%SY3o%QQ0Rx3qSYNuQ01-bw5ML$-g>s zchoLL;0fHWU+awiQfrUsPq+O<&0WawlfHY@QBhH_?9qm&f0M0~nRHv$TJvj7rF54T zdeTvRU*2AawKHychOSrViUp1)DW|TKnOXjrdAN4P3m&UKWU<4JPEKfk*jJ5D-S?M@ z%J%2tRl!^l{riQ1L#IMY<)TQq3N>>HIm3YNO;ZM47n<1K{CDqSq+gK6W@O-gtg;&P zSgjs0%Ti_;xY5>50VA{1(guJP6`!0eYhaM2f41`zm_Ciq2Aa9Kc};EY=I|p2UPz1( zd)mWqTHDj$k*@y!SmU;k&D9T+e|v6CZX9p*72OX_11a&a!K3`uO+KG}N58%LNx;b* zXY*W6*XKOtyJSQ*siK~IlYU2>hW;lvn*pj;U-J(?7O3z$@e)5fcCr6iCmnrV4B0nc zUS8{D<}tNU{P_123?`faCPBf$u}MjvpI>F)KUw!LbCb8T2OL5yq=^YV6p-wW2G1?C z&t=q$F~$SKrc%X!B5(bgdeD4$)&FRG5-d%-?VS76qkEJ7eP0vVg`8$Cp}@oH&X#EY zdGt2OOIS0dY6PZ;jf*?ie0J2VQ}vkW1u17PNP!*k&C)z!c)1Ch_`C!(tJz)KARB4>MKo7rK-t}<%56}w*MJbfsb|KFH#a7>m^0Hmg;m=ey zFt`q#SBR#JPflh7y&<}KRXUkVU$eB==O_rEIxZoh9ZnMPMvRXwEl+_0g97^;M#Nw% zh#F59U25%KGQO{?i@3jlSY__DDg_K|Y}kzk1QTb_|0o!u`-q2pZ|&#A1lcWnD$q&{ zjEwpEG<;gRx(e3TY`{$zSy(jg-#5`&n4N6{4;dWPmcG8SpVmvPj7r_b6wEStu^<;T zVAVVaJ>3#kX}c28?->4WQd;Ci3#@z!OUZB2j!8^H!f7hStdwG;0ZXR{BpUX6zNoAT zF#?iC#KgqN`OGi_FXNd2rPXdsY{?XH2P;=p;&|g?YHDi6ZKu`&jQedJ9ifn2`GAW1 zoo;21cMopa0&`B)YGdT&j0B-s5uwAut)s$}Se;};CD6TmGrDQ4Nw3K#H714-BG3!Y){)0IZo|;gDPQ6Ccg^)B&U+S>E8_ zK#n+sOl*337og;u($doEGf&VX!idK-A2^Ep} zUfTvWAiKTc8%iBVB&?I{g`7 z0)$}Y;Ftp~m5`ha*D`fGGztc%S5_j@(<#AC@bK`Mnx7AjjwbN)^8=sFtNd=9)!c^xjib55US6x}8`Y|Q^RClW)4NdLUt5?GucQJE_ zi$dg$UJ9`?*QrQpsOHHAhF}SAwG|?i(e)284k^bJ0E7_`1wDZ2f9fX1I!RiP+Kih#opezR^;iB4q*9H80dWgE|if)5{VL9)Mc^{UQR3|7C@L*H*>Lq!iD zS_mKt3f*gqir68Q?}(QupBFSfL1u>YF%4@Bd?;|lz&kQ540E9`TUA;bol?*iIg$$r ze(Q$_0D)Q7urvHfufZesnxRkZ$B_{!#J9%+h*km?Gqb!rJ}10RZRxboO%C^uesG|HEP&)S)W0>6 zEblcT@O4J3Z5}A%zaY#sNXO;)W?c=0j+laCY{jnZTz0U4j3&dq45dJ*515a?w`k37*yBOQ<9g* z0(&)Sr=hWtvp^6^B?HDBQWtIQ6XFcY3JMDgwb@O7);&3%Ch#``b{P~D6qBB==;b90 z%RB`gZ7+{R10TAtr8P9yX$jeeO4t>X$G!CM;DCsbFrdEPyCi2Gq)AfLJm{m^lb3{e z?`nC-MLl?ggoGgaO#~=BcZMDSgP)#i2}}yu+}djE>x%{`cV3$i`sK5w3ELT* zw;gF?V`D`R7xR=U`cr`~DRMVTDJkLp`t=LAWZH*Gzw}y{-?^;Vpe|?Jn~yThe{O7S z2%a2Ex@rnuV;(F}W#Q$G1v4@(Bg3{f?LPmbC*NM)1;2E{`N?aj$|1!#AnRV+i!BhV za;mBw5JfRDF}j(rZjOVE`EPXzs3INI3PHJD`1ZlU5Y7%6zXdL8y0atce`hMeZZ@n*u?j8q& zTzp&{MKK*%5uizR%jSRoCLtuG)z}Drd?$T^s&g0+B_0R@05L}k6n~%)7c^n5R+Xkl zAz1l>r}hzqKZ{BRWZ+1UO~=Q_VG$8#i{El~qI`*F`~Vnj*8~bmo~-}M{PIPPo`Hdv zA`;4mF>!INz|5eG$pm2oQ2IrSk}j=tO_v#uH&rQ#6rs&d?(Qrc91#d1s?0u7TKyY@ z7oQZK8YC|U^#+8%!*R^d&wn}ihoeAp*V$jU-<6ozf|z+PhZP&x9vu@?Fc^tQIi!m} zh{kW73uQsYr?LJgy0we10o_Pmv8nvnS0&krqJ5DZGR1g!nlci z3xM2w6$%YP&U2U`(I#qLLN_)Xu}DQ2jZK)1O_*+O1%u$Ob)Lrtkdcy+ffK_Y(Mg4%j|-Q}hoa*B$x;0Hi-Z-BY{45aYv%uKGE zXDjwU5BEn>-hzlIyII_9(WC}ve27c6Dh9GbP`H9wliF{(^BG)(W(UlKx$&vsodulm z-aER?f=UZGPjCnLc;k8g(3&;Htj6&m%>ZcH#hy1WS%>U&`OrN<1Xv1?dc(pK`SYd; zG=0yn{=iD*{_b`@m6e$8YZY9`AX9lowx%@Wfqu(m_x1s zpP`&Ua+Q))CH#L~zBw!ty)H~B^?U%#qIbU!B+s`gSNX@F58ZjM{R_fJ|20d6Xa8;H zr1e5y=VSc{iW2>=nGq%UU$ZKT=ijC)*?VE6Sv{X3X(vaX2Xm;dRlLb5}FC606Mt@7xWyf2Y>)&qqgx3b!;UKedzM~zd&?@eL8jQ>EO14$-ushhC1Bsv1|4l6&PlKn(pYabL2S#nU z&nr7=2a*LUnXR3j;nCvH7eZ-#mh|_gL%I3g*KUE)LPAM7-kbQgLw)r^&>|+dTjabZ zm%yDuqZJu1YI#yw*@(u<&Tf-DW{Z4C(z7v`m=!{~jgP-O`Xd=BaamiiVO%B^tWoLV zdz3mfVSo%7^6}#x6tjwGl#GU!Wvz_Hry#5joB#cL2th(hO5k@-@|KY*4lW%X9q4J? z5XptUNqI*{E-o%+!23%Wzxn)6Rp7F#Ff~|>h3+)zf_C%*0#|r2x+=`OFflQ~$c|iG zd<+%RODU>vto_z3_)=5AfCJA7$Q<~UOTO7q*!mnz6AiQ$2oU7zi-44BHk06cCE5Mo z9L>ni~PXQ7yToU!h>0wvmcA) zNU1S(+e-`_MyPE}O;10S$-A4^4-H^umo#20S#4V=|Kmu~1aw^Yjvx@!$%Rd8T8{~rDsr~+OE#@{7$^r8Bu{>O7rFfj)mw103A8xwN}Y)ViNkSL&@ z*n5vaEU2>5rQ`&B8g)(0O94D7isDKRlCR>k`KI!u07k6JwF^A9L^(7 zHn!HEKO6h&kchT~FC)N0!r=Kp0ao3^YU`^Q1lPgSn`;`62IJ?Z%`kky(VE2h2n99O zC&P;J@^qr288N+pPnHRc!p3cz44D{xNI#zkyul6 z`xUSO1t{YHQ78s`5&S~-&CSiEJ#ryuv&>cZwTU;#r2zQM=1O48OP}M-jwCy%<|RU< zm>s^u(gZ&!58Pj{Et%-(?jArPitWaRVr!p?0*2(TV5al literal 0 HcmV?d00001 diff --git a/images/latex/3fd61ab3fe88f694e70f61e4f8ea056b.svg b/images/latex/3fd61ab3fe88f694e70f61e4f8ea056b.svg new file mode 100644 index 00000000..f34f28db --- /dev/null +++ b/images/latex/3fd61ab3fe88f694e70f61e4f8ea056b.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/latex/fe880741c0d91317587412f1badeab3f.svg b/images/latex/fe880741c0d91317587412f1badeab3f.svg new file mode 100644 index 00000000..346c4f36 --- /dev/null +++ b/images/latex/fe880741c0d91317587412f1badeab3f.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/index.html b/index.html index a88f4696..fb92287b 100644 --- a/index.html +++ b/index.html @@ -912,9 +912,9 @@ function Bezier(3,t):

The following graphs show the interpolation functions for quadratic and cubic curves, with "S" being the strength of a point's - contribution to the total sum of the Bézier function. Click or - click-drag to see the interpolation percentages for each - curve-defining point at a specific t value. + contribution to the total sum of the Bézier function. Click-and-drag + to see the interpolation percentages for each curve-defining point + at a specific t value.

The function for rational Bézier curves has two more terms:

@@ -1093,35 +1093,51 @@ function Bezier(3,t,w[]): ratio1 = 0.5, and so on. The second term then corrects for all those multiplications by dividing the total value by the "basis" value of the Bézier curve, i.e. the value we - get by computing the curve without any weighting at (but + get by computing the curve without any weighting (but with ratios):

- -

So what does this actually do?

- Let's look at the effect of "rationalising" our Bézier curves by - interacting with the curve and ratios. The following graphic shows - the curve from the previous section, enriched with ratio factors: - the closer to zero we set one or more terms, the less relative - influence the associated coordinates exert on the curve (and of - course the higher we set them, the more influence they have). -

-

- <Graphic title="Our rational cubic Bézier curve" - setup={this.drawCubic} draw={this.drawCurve} sliders={[ {min:0, - max:2, value:1, step:0.01, label:ratio 1}, {min:0, - max:2, value:1, step:0.01, label:ratio 2}, {min:0, - max:2, value:1, step:0.01, label:ratio 3}, {min:0, - max:2, value:1, step:0.01, label:ratio 4} ]} - setSliders={this.setRatio} onSlide={this.changeRatio} - context={this}/> + So what does this actually do? Let's look at the effect of + "rationalising" our Bézier curves by interacting with the curve and + ratios. The following graphic shows the curve from the previous + section, enriched with ratio factors: the closer to zero we set one + or more terms, the less relative influence the associated coordinate + exerts on the curve (and of course the higher we set them, the more + influence they have).

+ + + + Scripts are disabled. Showing fallback image. + + ratio 1 + 1.0
+ ratio 2 + 1.0
+ ratio 3 + 1.0
+ ratio 4 + 1.0 +
+

You can think of the ratio values as each coordinate's "gravity": the higher the gravity, the closer to that coordinate the curve will diff --git a/ja-JP/index.html b/ja-JP/index.html index e691dd2d..d5c4a48e 100644 --- a/ja-JP/index.html +++ b/ja-JP/index.html @@ -705,7 +705,7 @@ function Bezier(3,t): ベジエ曲線は(すべての「スプライン」と同様に)補間関数です。これは点の集合を受け取って、それらの点のどこか「内側」の値を生成するということです。(このことから、制御点同士を結んで輪郭をつくったとき、その外側に位置する点は決して生成されないことがわかります。なお、この輪郭を曲線の「包」と呼びます。お役立ち情報でした!)実際に、補間関数によって生成された値に対する、各点の寄与の大きさを可視化することができますが、これを見れば、ベジエ曲線のどの場所でどの点が重要になるのかがわかります。

- 下のグラフは、2次ベジエ曲線や3次ベジエ曲線の補間関数を表しています。ここでSは、ベジエ関数全体に対しての、その点の寄与の大きさを示します。あるtにおいて、ベジエ曲線を定義する各点の補間率がどのようになっているのか、クリックやドラッグをして確かめてみてください。 + 下のグラフは、2次ベジエ曲線や3次ベジエ曲線の補間関数を表しています。ここでSは、ベジエ関数全体に対しての、その点の寄与の大きさを示します。あるtにおいて、ベジエ曲線を定義する各点の補間率がどのようになっているのか、クリックドラッグをして確かめてみてください。

The function for rational Bézier curves has two more terms:

@@ -823,35 +823,51 @@ function Bezier(3,t,w[]): ratio1 = 0.5, and so on. The second term then corrects for all those multiplications by dividing the total value by the "basis" value of the Bézier curve, i.e. the value we - get by computing the curve without any weighting at (but + get by computing the curve without any weighting (but with ratios):

- -

So what does this actually do?

- Let's look at the effect of "rationalising" our Bézier curves by - interacting with the curve and ratios. The following graphic shows - the curve from the previous section, enriched with ratio factors: - the closer to zero we set one or more terms, the less relative - influence the associated coordinates exert on the curve (and of - course the higher we set them, the more influence they have). -

-

- <Graphic title="Our rational cubic Bézier curve" - setup={this.drawCubic} draw={this.drawCurve} sliders={[ {min:0, - max:2, value:1, step:0.01, label:ratio 1}, {min:0, - max:2, value:1, step:0.01, label:ratio 2}, {min:0, - max:2, value:1, step:0.01, label:ratio 3}, {min:0, - max:2, value:1, step:0.01, label:ratio 4} ]} - setSliders={this.setRatio} onSlide={this.changeRatio} - context={this}/> + So what does this actually do? Let's look at the effect of + "rationalising" our Bézier curves by interacting with the curve and + ratios. The following graphic shows the curve from the previous + section, enriched with ratio factors: the closer to zero we set one + or more terms, the less relative influence the associated coordinate + exerts on the curve (and of course the higher we set them, the more + influence they have).

+ + + + Scripts are disabled. Showing fallback image. + + ratio 1 + 1.0
+ ratio 2 + 1.0
+ ratio 3 + 1.0
+ ratio 4 + 1.0 +
+

You can think of the ratio values as each coordinate's "gravity": the higher the gravity, the closer to that coordinate the curve will diff --git a/lib/custom-element/api/base-api.js b/lib/custom-element/api/base-api.js index e827259d..ffff558b 100644 --- a/lib/custom-element/api/base-api.js +++ b/lib/custom-element/api/base-api.js @@ -88,6 +88,13 @@ class BaseAPI { ); } + stopEvent(evt) { + if (evt.target === this.canvas) { + evt.preventDefault(); + evt.stopPropagation(); + } + } + /** * */ @@ -116,7 +123,7 @@ class BaseAPI { * */ onMouseDown(evt) { - stop(evt); + this.stopEvent(evt); this.cursor.down = true; this.getCursorCoords(evt); } @@ -125,7 +132,7 @@ class BaseAPI { * */ onMouseMove(evt) { - stop(evt); + this.stopEvent(evt); this.cursor.move = true; this.getCursorCoords(evt); } @@ -134,7 +141,7 @@ class BaseAPI { * */ onMouseUp(evt) { - stop(evt); + this.stopEvent(evt); this.cursor.down = false; this.cursor.move = false; this.getCursorCoords(evt); @@ -148,7 +155,7 @@ class BaseAPI { // going to allow unmodified keys, or shift-modified keys, // and tab has to always work. For obvious reasons. if (!evt.altKey && !evt.ctrlKey && !evt.metaKey && evt.key !== "Tab") { - stop(evt); + this.stopEvent(evt); } } @@ -184,6 +191,7 @@ class BaseAPI { canvas.setAttribute(`tabIndex`, 0); canvas.classList.add(`focus-enabled`); canvas._force_listener = () => { + /* // I have NO idea why forceFocus() causes a scroll, but // I don't have time to dig into what is no doubt deep // black spec magic, so: check where we are, force the @@ -194,8 +202,11 @@ class BaseAPI { // Oh yeah... using round() because apparently scrollTo // is not NOT idempotent and rounding errors cause it to // drift. IT'S FUCKING HILARIOUS + */ this.forceFocus(); + /* window.scrollTo(x, y); + */ }; [`touchstart`, `mousedown`].forEach((evtName) => canvas.addEventListener(evtName, canvas._force_listener) @@ -286,10 +297,4 @@ function enhanceContext(ctx) { return ctx; } -// Outright kill off an event. -function stop(evt) { - evt.preventDefault(); - evt.stopPropagation(); -} - export { BaseAPI }; diff --git a/lib/custom-element/api/graphics-api.js b/lib/custom-element/api/graphics-api.js index 44d36bb8..fff201a1 100644 --- a/lib/custom-element/api/graphics-api.js +++ b/lib/custom-element/api/graphics-api.js @@ -177,6 +177,7 @@ class GraphicsAPI extends BaseAPI { * custom element scoped querySelector */ find(qs) { + if (!this.element) return false; return enrich(this.element.querySelector(qs)); } @@ -184,6 +185,7 @@ class GraphicsAPI extends BaseAPI { * custom element scoped querySelectorAll */ findAll(qs) { + if (!this.element) return false; return Array.from(this.element.querySelectorAll(qs)).map((e) => enrich(e)); } diff --git a/lib/custom-element/api/types/bezier.js b/lib/custom-element/api/types/bezier.js index 8ecb6ced..56ed79f2 100644 --- a/lib/custom-element/api/types/bezier.js +++ b/lib/custom-element/api/types/bezier.js @@ -72,16 +72,16 @@ class Bezier extends Original { drawCurve() { const ctx = this.ctx; - const p = this.points; ctx.cacheStyle(); ctx.lineWidth = 2; ctx.strokeStyle = `#333`; ctx.beginPath(); - ctx.moveTo(p[0].x, p[0].y); - if (p[3]) { - ctx.bezierCurveTo(p[1].x, p[1].y, p[2].x, p[2].y, p[3].x, p[3].y); - } else { - ctx.quadraticCurveTo(p[1].x, p[1].y, p[2].x, p[2].y); + const lut = this.getLUT().slice(); + let p = lut.shift(); + ctx.moveTo(p.x, p.y); + while (lut.length) { + p = lut.shift(); + ctx.lineTo(p.x, p.y); } ctx.stroke(); ctx.restoreStyle(); diff --git a/package-lock.json b/package-lock.json index 91d9938f..b3a6e791 100644 --- a/package-lock.json +++ b/package-lock.json @@ -201,6 +201,12 @@ "fill-range": "^7.0.1" } }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -263,6 +269,16 @@ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "dev": true }, + "clean-html": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/clean-html/-/clean-html-1.5.0.tgz", + "integrity": "sha512-eDu0vN44ZBvoEU0oRIKwWPIccGWXtdnUNmKJuTukZ1de00Uoqavb5pfIMKiC7/r+knQ5RbvAjGuVZiN3JwJL4Q==", + "dev": true, + "requires": { + "htmlparser2": "^3.8.2", + "minimist": "^1.1.1" + } + }, "coa": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", @@ -313,6 +329,18 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -498,6 +526,15 @@ "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", "dev": true }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, "domutils": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", @@ -758,6 +795,48 @@ "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", "dev": true }, + "html": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/html/-/html-1.0.0.tgz", + "integrity": "sha1-pUT6nqVJK/s6LMqCEKEL57WvH2E=", + "dev": true, + "requires": { + "concat-stream": "^1.4.7" + } + }, + "htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "dev": true, + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "dev": true + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "http-proxy": { "version": "1.18.1", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", @@ -811,6 +890,12 @@ "minimatch": "^3.0.4" } }, + "indent": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/indent/-/indent-0.0.2.tgz", + "integrity": "sha1-jHnwgBkFWbaHA0uEx676l9WpEdk=", + "dev": true + }, "indent-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", @@ -2025,6 +2110,12 @@ "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", "dev": true }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, "typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", diff --git a/package.json b/package.json index db113c39..4d738cae 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "url": "https://github.com/Pomax/BezierInfo-2/issues" }, "scripts": { - "start": "rm -f .timing && run-s time lint:* build time", + "start": "rm -f .timing && run-s time lint:* build time && rm -f .timing", "test": "run-p server browser", "---": "---", "browser": "open-cli http://localhost:8000", @@ -35,9 +35,12 @@ "devDependencies": { "bezier-js": "^2.6.1", "canvas": "^2.6.1", + "clean-html": "^1.5.0", "fs-extra": "^9.0.1", "glob": "^7.1.6", + "html": "^1.0.0", "http-server": "^0.12.3", + "indent": "0.0.2", "marked": "^1.1.1", "npm-run-all": "^4.1.5", "nunjucks": "^3.2.2", diff --git a/tools/build/create-index-page.js b/tools/build/create-index-page.js index aaf36dce..22e92580 100644 --- a/tools/build/create-index-page.js +++ b/tools/build/create-index-page.js @@ -1,5 +1,6 @@ import fs from "fs-extra"; import path from "path"; + import prettier from "prettier"; import generateLangSwitcher from "./generate-lang-switcher.js"; import nunjucks from "nunjucks"; @@ -57,7 +58,11 @@ async function createIndexPages(locale, localeStrings, chapters) { const index = nunjucks.render(`index.template.html`, context); + // TODO: FIXME: Prettier is slow as hell, find an alternative that isn't... + const start = Date.now(); const data = prettier.format(index, { parser: `html` }); + const end = Date.now(); + console.log(`beautification for ${locale} took ${(end - start) / 1000}s`); if (locale === defaultLocale) { fs.writeFileSync(`index.html`, data, `utf8`); diff --git a/tools/build/markdown/preprocess-graphics-element.js b/tools/build/markdown/preprocess-graphics-element.js index b38d101d..e28fa1af 100644 --- a/tools/build/markdown/preprocess-graphics-element.js +++ b/tools/build/markdown/preprocess-graphics-element.js @@ -28,8 +28,9 @@ async function preprocessGraphicsElement(chapter, localeStrings, markdown) { // if there are no width/height attributes, inject them - // FIXME: This will not work if there is UI html that - // TODO: uses width/height attributes, of course! + // FIXME: This will not work if there is UI html that uses the + // TODO: width/height attributes, but the graphics-element + // does not, of course! [known bug] if (updated.indexOf(`width=`) === -1) updated = updated.replace( @@ -78,8 +79,7 @@ async function preprocessGraphicsElement(chapter, localeStrings, markdown) { } /** - * - * @param {*} src + * ...docs go here... */ async function generateFallbackImage(src, width, height) { // Get the sketch code diff --git a/tools/build/process-locale.js b/tools/build/process-locale.js index caf7a358..68b1ceca 100644 --- a/tools/build/process-locale.js +++ b/tools/build/process-locale.js @@ -23,6 +23,8 @@ nunjucks.configure(".", { autoescape: false }); * ...docs go here... */ async function processLocale(locale, localeStrings, chapterFiles) { + const start = Date.now(); + const defaultLocale = localeStrings.getDefaultLocale(); const localeFiles = chapterFiles[locale]; @@ -74,6 +76,9 @@ async function processLocale(locale, localeStrings, chapterFiles) { console.log(`${locale} fully localized.`); } + const end = Date.now(); + console.log(`Processing ${locale} took ${(end - start) / 1000}s`); + return chapters; } diff --git a/zh-CN/index.html b/zh-CN/index.html index ed481930..49dbbf24 100644 --- a/zh-CN/index.html +++ b/zh-CN/index.html @@ -686,7 +686,7 @@ function Bezier(3,t): 贝塞尔曲线是插值方程(就像所有曲线一样),这表示它们取一系列的点,生成一些处于这些点之间的值。(一个推论就是你永远无法生成一个位于这些控制点轮廓线外面的点,更普遍是称为曲线的外壳。这信息很有用!)实际上,我们可以将每个点对方程产生的曲线做出的贡献进行可视化,因此可以看出曲线上哪些点是重要的,它们处于什么位置。

- 下面的图形显示了二次曲线和三次曲线的差值方程,“S”代表了点对贝塞尔方程总和的贡献。点击或拖动点来看看在特定的t值时,每个曲线定义的点的插值百分比。 + 下面的图形显示了二次曲线和三次曲线的差值方程,“S”代表了点对贝塞尔方程总和的贡献。点击拖动点来看看在特定的t值时,每个曲线定义的点的插值百分比。

The function for rational Bézier curves has two more terms:

@@ -804,35 +804,51 @@ function Bezier(3,t,w[]): ratio1 = 0.5, and so on. The second term then corrects for all those multiplications by dividing the total value by the "basis" value of the Bézier curve, i.e. the value we - get by computing the curve without any weighting at (but + get by computing the curve without any weighting (but with ratios):

- -

So what does this actually do?

- Let's look at the effect of "rationalising" our Bézier curves by - interacting with the curve and ratios. The following graphic shows - the curve from the previous section, enriched with ratio factors: - the closer to zero we set one or more terms, the less relative - influence the associated coordinates exert on the curve (and of - course the higher we set them, the more influence they have). -

-

- <Graphic title="Our rational cubic Bézier curve" - setup={this.drawCubic} draw={this.drawCurve} sliders={[ {min:0, - max:2, value:1, step:0.01, label:ratio 1}, {min:0, - max:2, value:1, step:0.01, label:ratio 2}, {min:0, - max:2, value:1, step:0.01, label:ratio 3}, {min:0, - max:2, value:1, step:0.01, label:ratio 4} ]} - setSliders={this.setRatio} onSlide={this.changeRatio} - context={this}/> + So what does this actually do? Let's look at the effect of + "rationalising" our Bézier curves by interacting with the curve and + ratios. The following graphic shows the curve from the previous + section, enriched with ratio factors: the closer to zero we set one + or more terms, the less relative influence the associated coordinate + exerts on the curve (and of course the higher we set them, the more + influence they have).

+ + + + Scripts are disabled. Showing fallback image. + + ratio 1 + 1.0
+ ratio 2 + 1.0
+ ratio 3 + 1.0
+ ratio 4 + 1.0 +
+

You can think of the ratio values as each coordinate's "gravity": the higher the gravity, the closer to that coordinate the curve will