title: SVG loses shape smoothness changing its colors on click
body: <p>By clicking <strong>multiple times</strong> on an <code>anchor</code> to trigger a javascript function, <code>changeColor()</code>, to apply random colors, the edges of the SVG shape appear not smooth, as you can see (<a href="http://jsfiddle.net/mitma/816pxaqm/" rel="nofollow noreferrer">jsfiddle</a>):</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>const strokeData = {"character":"龥","strokes":["M 128 445 Q 222 525 301 653 Q 319 685 334 709 L 343 725 Q 351 746 367 763 Q 376 772 374 782 Q 374 791 361 801 Q 327 827 298 819 Q 290 819 293 806 Q 310 732 219 604 L 171 539 Q 133 492 33 396 Q 26 392 35 390 Q 43 390 110 431 L 128 445 Z","M 334 709 Q 386 675 447 629 Q 461 617 472 615 Q 478 615 482 624 Q 488 634 474 663 Q 459 700 343 725 C 314 731 309 725 334 709 Z","M 253 553 Q 224 546 246 534 Q 276 517 325 531 Q 423 558 435 563 Q 439 567 439 572 Q 437 586 406 590 Q 388 593 316 566 L 253 553 Z","M 147 441 Q 143 445 128 445 C 101 446 101 446 110 431 Q 125 406 140 365 Q 153 331 162 323 Q 174 311 176 321 Q 178 329 175 343 L 171 363 Q 161 394 153 422 C 148 441 148 441 147 441 Z","M 255 464 Q 233 477 223 476 Q 213 475 180 456 Q 172 453 147 441 C 120 428 124 416 153 422 Q 161 423 181 431 Q 212 442 216 437 Q 221 433 216 383 C 213 353 241 353 245 383 Q 251 431 265 445 C 272 454 272 454 255 464 Z","M 175 343 Q 180 343 186 345 Q 216 357 254 367 Q 261 368 259 373 Q 259 377 245 383 L 216 383 Q 213 383 171 363 C 144 350 145 341 175 343 Z","M 285 468 Q 261 473 255 470 Q 255 468 255 464 C 255 459 255 469 265 445 Q 272 429 278 405 Q 288 371 295 363 Q 305 352 310 361 Q 310 367 310 371 L 308 392 Q 298 434 298 450 C 297 465 297 465 285 468 Z","M 374 410 Q 386 441 396 454 Q 404 463 406 466 C 413 475 413 475 398 484 L 374 498 Q 360 506 347 499 Q 327 482 285 468 C 257 458 270 438 298 450 Q 300 451 310 455 Q 351 468 355 462 Q 357 461 357 459 Q 359 445 342 406 C 330 378 363 382 374 410 Z","M 310 371 Q 323 378 385 390 Q 392 391 392 398 Q 390 402 374 410 C 368 413 368 413 342 406 Q 333 404 308 392 C 281 379 283 358 310 371 Z","M 406 466 Q 424 400 427 396 Q 437 382 441 392 L 443 406 L 441 425 Q 434 470 433 482 C 432 494 432 494 420 500 Q 419 501 416 502 Q 398 508 394 504 Q 390 500 398 484 L 406 466 Z","M 519 439 Q 529 478 541 490 Q 555 506 540 514 Q 514 526 506 528 Q 496 531 484 525 Q 454 510 420 500 C 391 491 403 477 433 482 Q 445 484 454 487 Q 490 496 495 490 Q 496 490 496 487 Q 500 472 490 439 C 482 410 511 410 519 439 Z","M 443 406 Q 449 406 455 407 Q 490 416 527 419 Q 534 420 534 425 Q 534 429 519 439 C 519 439 519 439 490 439 Q 488 441 441 425 C 413 415 413 405 443 406 Z","M 169 267 Q 151 272 139 272 Q 134 270 133 267 Q 132 264 139 246 Q 167 188 145 104 Q 129 91 142 62 Q 151 43 160 37 Q 166 27 173 32 Q 192 50 192 163 Q 192 202 192 242 C 192 261 192 261 169 267 Z","M 347 278 Q 402 290 419 284 Q 433 278 435 258 Q 439 207 429 114 Q 431 98 416 98 Q 396 98 386 100 Q 380 100 377 98 Q 369 94 398 69 Q 419 47 431 22 Q 441 15 451 20 Q 455 22 459 25 Q 480 58 482 158 Q 476 267 486 283 Q 494 292 488 302 Q 484 307 472 314 Q 437 333 419 323 Q 409 319 388 316 Q 271 292 169 267 C 140 260 164 232 192 242 Q 208 248 231 254 L 248 257 Q 272 265 323 274 L 347 278 Z","M 244 188 Q 235 186 214 178 Q 201 174 217 164 Q 226 158 246 163 L 274 170 L 332 184 L 367 190 Q 376 194 396 198 Q 402 199 406 202 Q 415 209 397 218 Q 379 227 368 223 L 332 216 Q 327 216 274 196 L 244 188 Z","M 231 254 Q 231 251 233 246 Q 241 216 244 188 L 246 163 Q 252 102 256 93 Q 265 78 270 87 Q 274 97 274 170 L 274 196 Q 274 208 275 218 Q 276 239 274 243 Q 271 250 248 257 C 229 263 229 263 231 254 Z","M 332 184 Q 332 80 342 71 Q 343 71 347 71 Q 351 73 354 81 Q 360 98 367 190 L 368 223 Q 368 229 372 243 Q 376 259 368 267 Q 355 276 347 278 C 319 288 317 289 323 274 Q 331 257 332 216 L 332 184 Z","M 698 651 L 862 688 Q 908 700 914 708 Q 923 714 918 723 Q 913 729 903 734 Q 864 751 825 733 Q 808 727 794 723 Q 696 689 582 674 Q 548 668 572 653 Q 606 634 659 641 L 698 651 Z","M 657 540 Q 668 553 678 566 Q 699 594 712 608 Q 734 624 698 651 C 674 669 660 671 659 641 Q 659 617 641 563 Q 631 549 630 535 C 626 505 638 517 657 540 Z","M 596 531 Q 594 533 591 535 Q 571 549 557 543 Q 555 541 555 536 Q 555 525 561 515 Q 582 472 572 295 Q 566 269 566 245 Q 566 198 586 180 Q 595 171 604 180 Q 611 192 612 201 L 613 229 Q 615 239 615 265 Q 613 294 613 308 L 613 331 L 613 406 L 613 431 Q 613 455 615 506 C 615 517 615 517 596 531 Z","M 809 223 Q 809 216 817 201 Q 831 173 841 174 Q 855 176 869 209 Q 874 219 876 225 Q 882 242 878 272 Q 868 363 866 451 Q 866 463 868 472 Q 871 489 885 517 Q 892 533 886 539 Q 861 561 817 579 Q 802 583 780 576 Q 774 574 657 540 L 630 535 Q 608 533 596 531 C 566 527 585 503 615 506 Q 627 506 642 510 Q 710 527 768 538 Q 789 542 795 531 Q 809 514 811 453 Q 817 290 811 249 L 809 223 Z","M 613 406 L 618 406 Q 686 417 747 423 Q 768 428 759 440 Q 749 452 727 456 Q 710 459 613 431 C 584 423 583 406 613 406 Z","M 613 308 L 623 308 Q 708 317 761 319 Q 783 323 774 334 Q 762 357 718 354 Q 690 352 613 331 C 584 323 583 308 613 308 Z","M 612 201 L 621 201 L 809 223 C 839 226 835 232 811 249 Q 800 259 777 258 Q 753 257 613 229 C 584 223 582 201 612 201 Z","M 623 161 Q 608 95 455 -29 Q 447 -35 447 -37 Q 446 -41 460 -39 Q 480 -37 504 -27 Q 562 -4 640 76 Q 686 123 690 126 Q 695 131 697 137 Q 704 157 671 167 Q 652 174 641 174 Q 627 174 623 161 Z","M 757 157 Q 757 153 757 151 Q 758 140 774 118 Q 829 47 864 -7 Q 877 -29 892 -36 Q 898 -37 903 -33 Q 923 -23 917 25 Q 914 77 768 163 Q 761 169 757 157 Z"],"medians":[[[306,809],[331,777],[299,694],[261,628],[204,549],[134,471],[36,394]],[[343,709],[352,714],[418,680],[449,658],[470,627]],[[247,544],[296,542],[396,571],[430,571]],[[119,429],[133,427],[170,326]],[[157,429],[195,452],[229,454],[238,443],[232,399],[223,394]],[[180,349],[185,359],[223,372],[254,372]],[[261,467],[274,459],[282,444],[303,366]],[[294,468],[302,463],[319,466],[353,482],[378,469],[365,424],[346,415]],[[312,376],[342,394],[386,397]],[[399,500],[418,476],[436,400]],[[428,499],[438,494],[495,510],[511,504],[517,496],[513,469],[509,453],[497,445]],[[449,411],[455,420],[472,424],[512,429],[528,425]],[[140,265],[165,240],[171,216],[174,151],[162,84],[168,40]],[[176,266],[196,259],[400,303],[434,303],[452,293],[458,266],[459,170],[452,94],[438,71],[383,94]],[[226,173],[325,199],[399,208]],[[236,251],[256,233],[264,91]],[[330,271],[351,252],[345,75]],[[574,665],[607,659],[648,661],[853,714],[907,718]],[[667,636],[685,620],[651,553],[636,541]],[[563,537],[592,497],[590,223],[595,187]],[[601,525],[632,521],[792,558],[815,551],[843,521],[837,466],[846,276],[841,185]],[[616,412],[628,424],[686,434],[729,439],[750,433]],[[618,314],[628,322],[706,335],[741,336],[766,328]],[[617,208],[629,219],[775,239],[792,239],[800,230]],[[680,143],[651,136],[615,87],[554,27],[503,-10],[454,-36]],[[766,154],[877,36],[893,-2],[894,-22]]]}
  
  const fontSize = 45
  const fontBorderWidth = 6
  
  const item = strokeData
  const charCode = item.character.charCodeAt()
  const startingPoints = item.medians.map(i=&gt;({x:i[0][0],y:i[0][1]}))
  
  let pathes = ``
  let strokeStartPositions = []
  let randomColors = []
  
  function circlesIntersect(circle1, circle2) {
    const deltaX = circle1.x - circle2.x
    const deltaY = circle1.y - circle2.y
    const rSum = circle1.r + circle2.r
    return deltaX*deltaX + deltaY*deltaY &lt;= rSum * rSum
  }
  
  function anyCircleIntersects(circleArr) {
    for (const circle1 of circleArr) {
      for (const circle2 of circleArr) {
        if (circle1 !== circle2) {
          if (circlesIntersect(circle1,circle2))
            return true
        }
      }
    }
  }
  
  function calculate_point_on_other_side_of_p2(p1, p2, distance_p2_to_p3) {
    const deltaX = p1[0]-p2[0]
    const deltaY = p1[1]-p2[1]
    const distance_p1_to_p2 = Math.sqrt(deltaX*deltaX + deltaY*deltaY)
    const scale = distance_p2_to_p3 / distance_p1_to_p2
    let p3 = []
    p3[0] = p2[0] - deltaX * scale
    p3[1] = p2[1] - deltaY * scale
    return p3
  }
  
  let newSvgContent = ``
  function getRandomColors(){
    randomColors = [];
    strokeStartPositions = [];
    for (const [i,stroke] of item.strokes.entries()) {
      randomColors.push(randomColor());
      const strokeColor = randomColors[i]
      pathes += `    &lt;path d="${stroke}" fill="${strokeColor}"/&gt;\n`        
      let x = startingPoints[i].x
      x = i&lt;9 ? x-fontSize/4 : x-fontSize/2
      //x = x-fontSize/2
      let y = 900+fontSize/2-startingPoints[i].y
      //y = y-fontSize/2
  
      strokeStartPositions[i] = [x, y]
    }
  
    const t0 = Date.now()
    const whileFunction = anyCircleIntersects(strokeStartPositions.map(pos=&gt;{return {r:fontSize/2, x:pos[0], y:pos[1]}}))
    while (whileFunction) {
      if (Date.now() &gt; t0+1000) {
        //pass
        break
      }
      for (const [i,p1] of strokeStartPositions.entries()) {
        const p1X = p1[0]
        const p1Y = p1[1]
        for (const [j,p2] of strokeStartPositions.entries()) {
          if (i === j)
            continue
          const p2X = p2[0]
          const p2Y = p2[1]
          if (p1X === p2X)
            p2[0] = p2[0]+1
          if (p1Y === p2Y)
            p2[1] = p2[1]+1
          const p1Radius = i&lt;9 ? fontSize/2.5 : fontSize/1.75
          const p2Radius = j&lt;9 ? fontSize/2.5 : fontSize/1.75
          if (circlesIntersect({r:p1Radius, x:p1X, y:p1Y}, {r:p2Radius, x:p2X, y:p2Y})) {
            let newP2 = calculate_point_on_other_side_of_p2(p1, p2, 1)
            let newP1 = calculate_point_on_other_side_of_p2(p2, p1, 1)
            strokeStartPositions[i][0] = Math.round(newP1[0])
            strokeStartPositions[i][1] = Math.round(newP1[1])
            strokeStartPositions[j][0] = Math.round(newP2[0])
            strokeStartPositions[j][1] = Math.round(newP2[1])
          }
        }
      }
    }
  
    let texts = ``
    for (const [i,pos] of strokeStartPositions.entries()) {
      //const textColor = "#FFFFFF"
      const textColor = randomColors[i];
      const x = pos[0]
      const y = pos[1]
      texts += `    &lt;text fill="${textColor}" x="${x}" y="${y}"&gt;${i+1}&lt;/text&gt;\n`
    }
  
    newSvgContent = `&lt;style type="text/css"&gt;
  @import url('https://fonts.googleapis.com/css?family=Roboto');
  text {
  font-family: 'Roboto', sans-serif;
  font-size: ${fontSize}px;
  paint-order: stroke;
  stroke: #1D1E22;
  stroke-width: 6px;
  stroke-linecap: butt;
  stroke-linejoin: miter;
  font-weight: 800;
  }
  &lt;/style&gt;
  &lt;g transform="scale(1, -1) translate(0, -900)"&gt;
  ${pathes} 
  &lt;/g&gt;
  &lt;g&gt;
  ${texts}
  &lt;/g&gt;`
  
    return newSvgContent
  }
  
  const svgEl = document.createElementNS("http://www.w3.org/2000/svg", "svg")
  svgEl.setAttribute("id", "svg");
  svgEl.setAttribute("version", "1.1");
  svgEl.setAttribute("viewBox", "0 0 1024 1024");
  svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg");
  getRandomColors();
  svgEl.innerHTML = newSvgContent
  document.body.appendChild(svgEl)
  
  //const canvasBbox = svgEl.getBBox()
  
  //const cx = canvasBbox.x + canvasBbox.width/2;
  //const cy = canvasBbox.y + canvasBbox.height/2;
  
  //const x = -cx * (0.7 - 1)
  //const y = -cy * (0.7 - 1)
  
  ////svgEl.style.transform = "scale(0.7)  translate(0px, -"+y+"px)"
  //svgEl.style.transform = "scale(0.7)"
  
  function changeColor(){
    var svg = document.getElementById("svg");
    var cloneElement = svg.cloneNode(true);
    getRandomColors();
    cloneElement.innerHTML = newSvgContent
    svg.parentNode.replaceChild(cloneElement, svg);
  }
  
  document.getElementById("changeColor").addEventListener("click", function() {
    changeColor();
  }, false);</code></pre>
  <pre class="snippet-code-css lang-css prettyprint-override"><code>* {
    padding: 0;
    margin: 0;
    border: 0;
  }
  html, body {
    width: 100%;
    height: 100%;
    background-color: #1D1E22;
    color: #e2e1e0;
  }
  svg {
    width: 100%;
    height: 100%;
    display: block;
    margin: 0 auto;
  }
  ul {
    text-align: center;
    list-style: none;
    margin-top: 30px;
  }
  ul li {
    display: inline-block;
  }
  ul li:before {
    content: "\07C \020";
    color: #e2e1e0;
  }
  ul li:last-child:after {
    content: "\020 \07C";
  }
  a, a:visited, a:focus, a:active {
    text-decoration: none;
    color: #53D633;
    outline: 0;
  }
  .sliding-middle-out {
    display: inline-block;
    position: relative;
    padding-bottom: 1px;
  }
  .sliding-middle-out:after {
    content: '';
    display: block;
    margin: auto;
    height: 1px;
    width: 0px;
    background: transparent;
  
    -webkit-transition: width 250ms ease-in-out, background-color 250ms ease-in-out;
    -moz-transition: width 250ms ease-in-out, background-color 250ms ease-in-out;
    -ms-transition: width 250ms ease-in-out, background-color 250ms ease-in-out;
    -o-transition: width 250ms ease-in-out, background-color 250ms ease-in-out;
    transition: width 250ms ease-in-out, background-color 250ms ease-in-out;
  }
  .sliding-middle-out:hover:after {
    width: 100%;
    background: #53D633;
    outline: 0;
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/randomcolor/0.5.2/randomColor.min.js"&gt;&lt;/script&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href="#" id="changeColor" title="Change Chinese character colors" class="sliding-middle-out"&gt;Change Colors&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>The behavior is different if instead I update the webpage or the code playground, as you can see.</p>
  
  <p>I don't understand the reason and so a possible solution, searching for a way to redraw the svg on click...</p>
  
  <p>The used code to replace the svg seems to not solve.</p>
  
  <p>Thank you for your help</p>