I'm trying to add a point into a SVG-Path at a certain position on the path.
<svg width="190" height="160" xmlns="http://www.w3.org/2000/svg">
<path d="M 48 241 C 50 13 129 26 130 238 C 138 521 214 431 220 228 C 237 65 288 -18 316 240" stroke="black" fill="transparent"/>
</svg>
Furthermore, I would like to add a point in the Path (curve), so that the path (curve) doesn't deform.
The point is e.g. "C x1 y1 x2 y2 210 331".
My question:.
How can I determine the controls x1 y1 x2 y2?
E.g. "C 100 100 100 500 210 331" is wrong, because the curve will be deformed.
<svg width="190" height="160" xmlns="http://www.w3.org/2000/svg">
<path d= "M 48 241 C 50 13 129 26 130 238 C 100 100 100 500 210 331 C 210 331 210 331 220 228 C 237 65 288 -18 316 240" stroke="black" fill="transparent"/>
</svg>
In other words the point (x = 210, y = 331) is given. Wanted are controls "x1 y1 x2 y2".
See here for more explanation
(In order to add a graphic in “stackoverflow.com”, it is needed some points. But I haven’t enough points, therefore I inserted a link)
Thanks in advance.
So all started when I saw this numerical sequence onto a reddit post:
0 1 3 4 6 8 9 10 12 14 16 18 19 20 21 22 24 26 28 30 32 34 36 38 39 40 41 42 43 44 45 46 48 50 52 54 56 58 60 62 64 66 68 70 72 74 76 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 96 98 100 102 104 106 108 110 112 114 116 118 120 122 124 126 128 130 132 134 136 138 140 142 144 146 148 150 152 154 156 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 192 194 196 198 200 202 204 206 208 210 212 214 216 218 220 222 224 226 228 230 232 234 236 238 240 242 244 246 248 250 252 254 256 258 260 262 264 266 268 270 272 274 276 278 280 282 284 286 288 290 292 294 296 298 300 302 304 306 308 310 312 314 316 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 384 386 388 390 392 394 396 398 400 402 404 406 408 410 412 414 416 418 420 422 424 426 428 430 432 434 436 438 440 442 444 446 448 450 452 454 456 458 460 462 464 466 468 470 472 474 476 478 480 482 484 486 488 490 492 494 496 498 500 502 504 506 508 510 512 514 516 518 520 522 524 526 528 530 532 534 536 538 540 542 544 546 548 550 552 554 556 558 560 562 564 566 568 570 572 574 576 578 580 582 584 586 588 590 592 594 596 598 600 602 604 606 608 610 612 614 616 618 620 622 624 626 628 630 632 634 636 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753
And as the author pointed out:
If you ignore the 0, I figured that it starts adding 2 one time, then 1 one time then 2 two times, 1 two times... 2 2n times, 1 2n times.
That's why I thought it's pretty easy thinking of a program that will return element n of the numerical sequence. So I came up with the following code (in javascript):
function pot(x, y){
if(y == 0){
return 1;
}else{
return pot(x, --y) * x;
}
}
function f2(x){
var n = 0;
var count = 0;
var progCount = 0;
var sw = true;
var current = 1;
while(progCount < x){
if(sw){
current += 2;
}else{
current += 1;
}
count++;
if(pot(2,n) == count){
if(!sw){
n++;
}
sw = !sw;
count = 0;
}
progCount++;
}
return current;
}
However I still wasn't able to convert this into a math formula... What made me think a lot. Something in my head tells me there has to be a way to convert such basic programs into a math formula.
That's why I came here to ask the following 2 questions:
1) Do you know a way to create a math formula for the numerical
sequence?
2) Is there a generic way to create a formula by a given
code.
Thank you in advance.
Not sure if it will help you, but:
function fun(n) {
var result, geo;
geo = result = parseInt(Math.log(n + 1) / Math.log(2), 10);
result = ((Math.pow(2, geo) - 2) / 2) * 3;
var diff = n - (Math.pow(2, geo) - 1);
geo = Math.pow(2, geo - 1);
result += (diff >= geo) ? geo * 2 + (diff - geo) : diff * 2;
return result + 1;
}
var result = "";
for(var i = 1; i < 100; ++i) {
result += fun(i) + ", ";
}
console.log(result);
Tested it up to n = 100.
You could use this function for calculating any value.
function f(n) {
function pow2(n) { return Math.pow(2, n); }
var t = Math.floor(Math.log(n) / Math.log(2)),
delta = n - pow2(t);
return n < 2 ? n : pow2(t) + n - (delta < pow2(t - 1) ? pow2(t - 1) - delta : 1);
}
function f(n) {
function pow2(n) { return Math.pow(2, n); }
var t = Math.floor(Math.log(n) / Math.log(2)),
delta = n - pow2(t);
return n < 2 ? n : pow2(t) + n - (delta < pow2(t - 1) ? pow2(t - 1) - delta : 1);
}
var i;
for (i = 0; i < 200; i++) {
document.getElementById('tt').appendChild(document.createTextNode(i + ': ' + f(i) + '\n'));
}
<pre id="tt"></pre>
You can use String.prototype.match() with RegExp /\d+/g to get all numbers as an array, Array.prototype.reduceRight(), Array.prototype.unshift(), Array.prototype.reduce(); mathematically use addition, subtraction to determine sequence of difference between numbers, and rebuild the original set from the sequence derived from original set.
let pattern = `0 1 3 4 6 8 9 10 12 14 16 18 19 20 21 22 24 26 28 30 32
34 36 38 39 40 41 42 43 44 45 46 48 50 52 54 56 58 60 62
64 66 68 70 72 74 76 78 79 80 81 82 83 84 85 86 87 88 89
90 91 92 93 94 96 98 100 102 104 106 108 110 112 114 116
118 120 122 124 126 128 130 132 134 136 138 140 142 144
146 148 150 152 154 156 158 159 160 161 162 163 164 165
166 167 168 169 170 171 172 173 174 175 176 177 178 179
180 181 182 183 184 185 186 187 188 189 190 192 194 196
198 200 202 204 206 208 210 212 214 216 218 220 222 224
226 228 230 232 234 236 238 240 242 244 246 248 250 252
254 256 258 260 262 264 266 268 270 272 274 276 278 280
282 284 286 288 290 292 294 296 298 300 302 304 306 308
310 312 314 316 318 319 320 321 322 323 324 325 326 327
328 329 330 331 332 333 334 335 336 337 338 339 340 341
342 343 344 345 346 347 348 349 350 351 352 353 354 355
356 357 358 359 360 361 362 363 364 365 366 367 368 369
370 371 372 373 374 375 376 377 378 379 380 381 382 384
386 388 390 392 394 396 398 400 402 404 406 408 410 412
414 416 418 420 422 424 426 428 430 432 434 436 438 440
442 444 446 448 450 452 454 456 458 460 462 464 466 468
470 472 474 476 478 480 482 484 486 488 490 492 494 496
498 500 502 504 506 508 510 512 514 516 518 520 522 524
526 528 530 532 534 536 538 540 542 544 546 548 550 552
554 556 558 560 562 564 566 568 570 572 574 576 578 580
582 584 586 588 590 592 594 596 598 600 602 604 606 608
610 612 614 616 618 620 622 624 626 628 630 632 634 636
638 639 640 641 642 643 644 645 646 647 648 649 650 651
652 653 654 655 656 657 658 659 660 661 662 663 664 665
666 667 668 669 670 671 672 673 674 675 676 677 678 679
680 681 682 683 684 685 686 687 688 689 690 691 692 693
694 695 696 697 698 699 700 701 702 703 704 705 706 707
708 709 710 711 712 713 714 715 716 717 718 719 720 721
722 723 724 725 726 727 728 729 730 731 732 733 734 735
736 737 738 739 740 741 742 743 744 745 746 747 748 749
750 751 752 753`;
let arr = pattern.match(/\d+/g);
let sequence = [];
let first = arr.reduceRight((a, b) => {sequence.unshift(a-b); return b});
sequence.unshift(+first);
console.log(sequence);
let rebuild = [sequence[0]];
sequence.reduce((a, b) => {rebuild.push(a+b); return rebuild[rebuild.length-1]});
console.log(rebuild);
plnkr http://plnkr.co/edit/DrVDjDTOTNzCJ0sSEk3q?p=preview
when I analyze the results the following applies:
when n is power of 2, the result is always equal to n*1.5
when n is power of 2, result of next n are added with 2 with maximum of the difference of result-n-1, eg. result of n=8 equals 12 and 8 is power of 2, in this case the following n => result are 8=>12, 9 => 14, 10 => 16, 12 => 18. The other values until next n is equal power are added with 1
Because of this formula will be like as follow:
Math.pow(2, Math.floor(Math.log2(n)))*1.5+n%Math.pow(2,Math.floor(Math.log2(n))) + (n<Math.pow(2, Math.floor(Math.log2(n)))*1.5-1 ? x-Math.pow(2, Math.floor(Math.log2(n))) : Math.pow(2, Math.floor(Math.log2(n)))*0.5-1)
or as function:
var fn = function (n) {
var r0 = Math.pow(2, Math.floor(Math.log2(n)));
var r1 = r0 * 1.5 + n % r0;
var r2 = n < r0 * 1.5 - 1 ? n - r0 : r0 * .5 - 1;
return r1 + r2;
}
following loop will show the same result as numerical sequence
for (i = 1; i < 499; i++) {
console.log(fn(i));
}
you can try polynomial interpolation
In numerical analysis, polynomial interpolation is the interpolation of a given data set by a polynomial: given some points, find a polynomial which goes exactly through these points.
https://en.wikipedia.org/wiki/Polynomial_interpolation
Try it out with wolframalpha
http://www.wolframalpha.com/input/?i=interpolate+(1,1)+(2,3)+(3,4)+(4,6)+(5,8)+(6,9)+(7,10)+(8,12)+(9,14)+(10,16)
It gives you this function ( just copy and paste in javascript, it gaves you the solution between x[1,10] )
f(x) = -x^9/60480+(37 x^8)/40320-(107 x^7)/5040+(767 x^6)/2880-(5677 x^5)/2880+(50539 x^4)/5760-(693913 x^3)/30240+(110741 x^2)/3360-(5897 x)/280+5
x is the position of your list
f(x) is your solution
f(1) = 1
f(2) = 3
f(3) = 4
..
f(10) = 16
f(x>10) = is probably crap, because there are no known data points
Greetings
I'm using an SVG textpath to animate a word around a closed path. How can I get the animation to treat the path as a circle, and have the text smoothly transition from the end of the path to the beginning? Right now it finishes drawing the text (clipping the spillover), till the text disappears, then starts again at the beginning by popping the word back at the start.
<html><head>
<style type="text/css">
html {width: 100%; height: 100%;}
body {width: 100%; height: 100%; margin: 0; padding: 0;}
svg {width: 100%; height: 100%;}
text {fill: deepPink; font-size: 9em;}
</style>
</head>
<body>
<svg viewBox="0 0 800 600">
<path id="myPath" fill="none" stroke="#999999" stroke-width=45 stroke-miterlimit="10" stroke-linecap="round" d="M 305 99 L 313 104 L 319 108 L 323 114 L 328 116 L 333 122 L 338 125 L 358 125 L 367 114 L 369 108 L 381 111 L 407 111 L 417 104 L 421 104 L 433 106 L 441 105 L 452 108 L 481 99 L 499 103 L 539 92 L 546 94 L 562 102 L 567 102 L 579 102 L 589 105 L 604 119 L 623 150 L 637 167 L 648 185 L 651 194 L 653 209 L 664 235 L 670 253 L 671 279 L 677 295 L 678 305 L 676 318 L 678 329 L 685 348 L 687 370 L 686 380 L 677 398 L 674 402 L 666 410 L 651 439 L 643 451 L 629 465 L 601 476 L 596 477 L 578 473 L 570 473 L 553 478 L 538 476 L 520 483 L 497 493 L 477 496 L 471 497 L 463 500 L 439 517 L 433 519 L 427 522 L 410 522 L 394 523 L 382 521 L 377 520 L 367 518 L 356 511 L 343 505 L 329 503 L 320 503 L 300 505 L 267 514 L 234 523 L 212 526 L 205 526 L 193 522 L 178 515 L 160 512 L 155 509 L 138 483 L 135 476 L 135 468 L 141 455 L 142 446 L 139 434 L 138 419 L 138 374 L 136 360 L 135 356 L 140 347 L 145 331 L 146 324 L 141 305 L 141 294 L 142 283 L 161 242 L 166 232 L 175 225 L 179 212 L 193 204 L 195 199 L 199 185 L 199 178 L 207 171 L 216 168 L 226 165 L 230 158 L 228 146 L 228 140 L 233 127 L 237 115 L 243 110 L 259 111 L 267 110 L 280 108 L 292 102 L 297 102 Z"/>
<path fill="none" stroke="#FFFF00" stroke-width= 3 stroke-miterlimit="10" stroke-linecap="round" d="M 305 99 L 313 104 L 319 108 L 323 114 L 328 116 L 333 122 L 338 125 L 358 125 L 367 114 L 369 108 L 381 111 L 407 111 L 417 104 L 421 104 L 433 106 L 441 105 L 452 108 L 481 99 L 499 103 L 539 92 L 546 94 L 562 102 L 567 102 L 579 102 L 589 105 L 604 119 L 623 150 L 637 167 L 648 185 L 651 194 L 653 209 L 664 235 L 670 253 L 671 279 L 677 295 L 678 305 L 676 318 L 678 329 L 685 348 L 687 370 L 686 380 L 677 398 L 674 402 L 666 410 L 651 439 L 643 451 L 629 465 L 601 476 L 596 477 L 578 473 L 570 473 L 553 478 L 538 476 L 520 483 L 497 493 L 477 496 L 471 497 L 463 500 L 439 517 L 433 519 L 427 522 L 410 522 L 394 523 L 382 521 L 377 520 L 367 518 L 356 511 L 343 505 L 329 503 L 320 503 L 300 505 L 267 514 L 234 523 L 212 526 L 205 526 L 193 522 L 178 515 L 160 512 L 155 509 L 138 483 L 135 476 L 135 468 L 141 455 L 142 446 L 139 434 L 138 419 L 138 374 L 136 360 L 135 356 L 140 347 L 145 331 L 146 324 L 141 305 L 141 294 L 142 283 L 161 242 L 166 232 L 175 225 L 179 212 L 193 204 L 195 199 L 199 185 L 199 178 L 207 171 L 216 168 L 226 165 L 230 158 L 228 146 L 228 140 L 233 127 L 237 115 L 243 110 L 259 111 L 267 110 L 280 108 L 292 102 L 297 102 Z"/>
<text>
<textpath xlink:href="#myPath">Autotopia
<animate attributeName="startOffset" from="0%" to="100%" begin="0s" dur="10s" repeatCount="indefinite"/>
</textpath>
</text>
</svg>
</body></html>
Code sample at mvjantzen.com/mobility/svganimatedtext.html
How about having the path repeat (so it goes round twice) then animate from 0 to 50%
You can use the snap svg library to achieve this:
http://jsbin.com/gixomogiwo/1/edit
And here is the code:
var s = Snap(800,800);
var path = "M 305 99 L 313 104 L 319 108 L 323 114 L 328 116 L 333 122 L 338 125 L 358 125 L 367 114 L 369 108 L 381 111 L 407 111 L 417 104 L 421 104 L 433 106 L 441 105 L 452 108 L 481 99 L 499 103 L 539 92 L 546 94 L 562 102 L 567 102 L 579 102 L 589 105 L 604 119 L 623 150 L 637 167 L 648 185 L 651 194 L 653 209 L 664 235 L 670 253 L 671 279 L 677 295 L 678 305 L 676 318 L 678 329 L 685 348 L 687 370 L 686 380 L 677 398 L 674 402 L 666 410 L 651 439 L 643 451 L 629 465 L 601 476 L 596 477 L 578 473 L 570 473 L 553 478 L 538 476 L 520 483 L 497 493 L 477 496 L 471 497 L 463 500 L 439 517 L 433 519 L 427 522 L 410 522 L 394 523 L 382 521 L 377 520 L 367 518 L 356 511 L 343 505 L 329 503 L 320 503 L 300 505 L 267 514 L 234 523 L 212 526 L 205 526 L 193 522 L 178 515 L 160 512 L 155 509 L 138 483 L 135 476 L 135 468 L 141 455 L 142 446 L 139 434 L 138 419 L 138 374 L 136 360 L 135 356 L 140 347 L 145 331 L 146 324 L 141 305 L 141 294 L 142 283 L 161 242 L 166 232 L 175 225 L 179 212 L 193 204 L 195 199 L 199 185 L 199 178 L 207 171 L 216 168 L 226 165 L 230 158 L 228 146 L 228 140 L 233 127 L 237 115 L 243 110 L 259 111 L 267 110 L 280 108 L 292 102 L 297 102 Z";
setInterval(function(){ var text = s.text(50,50,'Autotopia')
.attr({ 'textpath': path,'font-size' : '3em' })
.textPath.animate({ 'startOffset': 3000 }, 5000 ); }, 5000);
I have a chart generated using RaphaelJS library. It is just on long path:
M 50 122 L 63.230769230769226 130 L 76.46153846153845 130 L
89.6923076923077 128 L 102.92307692307692 56 L 116.15384615384615 106 L 129.3846153846154 88 L 142.6153846153846 114 L 155.84615384615384 52
L 169.07692307692307 30 L 182.3076923076923 62 L 195.53846153846152
130 L 208.76923076923077 74 L 222 130 L 235.23076923076923 66 L
248.46153846153845 102 L 261.6923076923077 32 L 274.9230769230769 130 L 288.15384615384613 130 L 301.38461538461536 32 L 314.6153846153846
86 L 327.8461538461538 130 L 341.07692307692304 70 L
354.30769230769226 130 L 367.53846153846155 102 L 380.7692307692308 120 L 394 112 L 407.2307692307692 68 L 420.46153846153845 48 L
433.6923076923077 92 L 446.9230769230769 128 L 460.15384615384613 110 L 473.38461538461536 78 L 486.6153846153846 130 L 499.8461538461538 56
L 513.0769230769231 116 L 526.3076923076923 80 L 539.5384615384614 58
L 552.7692307692307 40 L 566 130 L 579.2307692307692 94 L
592.4615384615385 64 L 605.6923076923076 122 L 618.9230769230769 98 L 632.1538461538461 120 L 645.3846153846154 70 L 658.6153846153845 82 L 671.8461538461538 76 L 685.0769230769231 124 L 698.3076923076923 110 L 711.5384615384615 94 L 724.7692307692307 130 L 738 130 L 751.2307692307692 66 L 764.4615384615385 118 L 777.6923076923076 70 L 790.9230769230769 130 L 804.1538461538461 44 L 817.3846153846154 130 L 830.6153846153845 36 L 843.8461538461538 92 L 857.076923076923 130 L 870.3076923076923 76 L 883.5384615384614 130 L 896.7692307692307 60 L 910 88
Also below these chart I have a jqueryUI slider of the same width (860px) and centered with the chart. I want when I move the slider to move a dot on the chart accordingly with the slider position. See attached screenshot:
As you can see it seems to work fine. I've implemented this behaviour using the pathIntersection() method. On the slide event at each ui.value (x coordinate) I intersect my chartPath (the one from above) with a vertical straight line at the x coordinate.
But still there are some problems. One of them is that it runs very hard, and it kinda freezes sometimes.. and very weird sometimes it doesn't seem to intersect at all even it should.. I'll example below 2 cases I identified:
M 499.8461538461538 0 L 499.8461538461538 140
M 910 0 L 910 140
Could you please explain why this intersect behaviour happens (it should return a dot).. and the worst part it seems like it happens randomly.. if I use another chartdata.
Also if you can identify another (better) solution to syncronise the slider position with the dot on the chart.. would be perfect.
I thought about using Element.getPointAtLength(length), but I don't know how. I think I should save the pathSegments and for each to compute the start Length and the finish Length.
I think it would be better to use the source data to find the intersection point manually. Shouldn't be too hard as the points are already sorted by x.
Path intersection appears to fail when you check the intersection at one of the vertices, which can be considered a bug but is not really surprising, since the library was never intended for computation geometry in the first place.
By way of quick hack you could also try slightly modifying the x value when pathIntersection fails to produce a single value and checking again, e.g. try 499.8461538461538 + 0.0001 * (2 * Math.random() - 1) instead of just 499.8461538461538. You might need to try several times before you get a proper answer, but here it is unlikely. I believe the technique is generally known as perturbation.
I was looking through some of the files used in Vexflow and I'm trying to add new glyphs for the score however, I don't know what code is being used here in the vex.flow.font.js file:
Vex.Flow.Font = {"glyphs":{"vb":{"x_min":0,"x_max":428.75,"ha":438,"o":"m 262 186 b 273 186 266 186 272 186 b 274 186 273 186 274 186 b 285 186 274 186 280 186 b 428 48 375 181 428 122 b 386 -68 428 12 416 -29 b 155 -187 329 -145 236 -187 b 12 -111 92 -187 38 -162 b 0 -51 4 -91 0 -72 b 262 186 0 58 122 179 "}
To my understanding, the code above is referenced by another file (glyph.js) to render an svg. Any help would be greatly appreciated, thank you :)
Vex.Flow.Font = {"glyphs": {
"vb": {
"x_min": 0,
"x_max": 428.75,
"ha": 438,
"o": "m 262 186 b 273 186 266 186 272 186 b 274 186 273 186 274 186 b 285 186 274 186 280 186 b 428 48 375 181 428 122 b 386 -68 428 12 416 -29 b 155 -187 329 -145 236 -187 b 12 -111 92 -187 38 -162 b 0 -51 4 -91 0 -72 b 262 186 0 58 122 179 "}}}
glyphs is a list of glyphs, mapping them from their code to their info. So vb is a glyph code, and the map with four values is its description. x_min and x_max describe horizontal metrics. x_min set to zero means start drawing the glyph at the current cursor point, and the value of x_max specifies cursor's movement to the right. I have no idea what is ha and what does it do. o is the outline of the glyphs to be rendered. It is described in a format similar to SVG paths. For the start, m 262 186 means move to pixel (262, 186), b 273... means draw a bezier curve with these points, etc.