preface

With the increasing of data today, the demand for data visualization is also increasing.

Open any recruitment app, and at least three out of ten of the slightly better jobs require experience in data visualization.

I once encountered such a demand: Qingdao Bank wanted to transform itself into a smart bank, so it put forward many requirements for exhibition items.

One of the projects is called the Cultural experience table, which includes a map of Qingdao, on which there are several coordinate points sent from the background. Clicking on the coordinate points will show the detailed information.

If you are from Qingdao in front of the screen or happen to be in Qingdao area, you can go to the Bank of Qingdao

I made the cultural experience table inside

Technology selection

Baidu map

At the beginning is definitely want to take Baidu map open platform API to do, after all, they are professional map, with this method both save time and effort at the same time the effect is good.

And not only can display as we usually search out the kind of professional map, but also can use the personalized map it provides:

But the security of banks is well known. In order to prevent hacker attacks, all banks are forbidden to connect to the Internet.

So you might say, well, isn’t there an offline version of the map tiles on the Internet? Make an offline map?

After searching for a long time, I found that these map tiles are not easy to find. I spent money to download a lot of them, but they are just some crippled versions, with incomplete functions and all kinds of pits. Basically, they are pirated versions.

Shark-eyed friends may have noticed that there is a Logo of Baidu map in the lower left corner of the map. After asking Party A, they clearly put forward that they do not want to appear any Logo except the advertiser data transmitted from Qingdao Bank or the background.

Why don’t you find a way to remove it or hide it?

That’s not good, because that’s what the Logo is for: Look! This is a map made by Baidu!

After all, if which company to make a map software, directly call baidu map API, and then delete the Logo, who can see this is Baidu map? I thought this was a map made by this company.

With my guess in mind, I carefully consulted the terms of use of Baidu Map:

Then you may be thinking: There are autonavi maps, Tencent Maps, Google Maps and other maps?

In fact, we are all the same, no one wants to work hard to make the map to be erased by others after the Logo as their own map, so there is no way to remove the Logo (forced removal will only be sent to the lawyer’s letter and then go to court to lose the lawsuit and lose money to bankruptcy).

ECharts

After communication with party a’s I learned: the cultural experience table is not really to give directions, like a professional map it primarily for the purpose of the show of shandong culture at the same time show a few points on the map, by the way () the coordinates of advertisers, click after the coordinates of the corresponding advertisers information, it contains the specific location.

In fact, it is also reasonable to think carefully, after all, even if you use Baidu so professional map, people will not carefully look at the coordinates in which the street which building, but directly click on the coordinates pop-up information: Qingdao XX Co., LTD., is located in XX Street XX building XX…

Then it would be so much easier! Just an abstract map to describe the outline of Qingdao city can be! So the first thing that comes to mind is ECharts:

Leadership after seeing renderings feel very satisfied: so both concise and cool, it!

So I finished writing a version with ECharts and tested it on the Splice screen (the cultural experience Table is two 1920 * 1080 screens stitched together horizontally), and I found this very upsetting thing:

The splicing screen is touch!

You may be thinking, “What’s the matter, touch is touch, and all the fuss!”

However, on the touch screen, I found that EChart map is controlled by mouse wheel to zoom in and out, which has no effect on the touch screen, and the current demand is to use two fingers to zoom in and out of the map like on the phone:

You might be thinking: This requirement is common on mobile, so there must be a library available for it.

Yes, but then it will become blurred after zooming in, because the underlying ECharts is drawn on Canvas, not vector, so it will cause distortion.

In addition, after mandatory zooming in, the stroke of the map will also be zooming in. Supposedly, the edge is only used for boundary division, which does not exist in reality, so it should be as thin as possible. In this case, we can only change the ECharts and then rely on the bottom Canvas to zoom in and out again.

No way, directly to see ECharts source code! Let’s see if we can change the logic that it redraws with the mouse wheel to two-finger zoom…

After reading the source code for half a day, I found that this logic is not in ECharts, but in ZRender which it depends on, I am too difficult! Check out the source code in ZRender:

It does define mobile events, so why doesn’t the map work? What does ECharts encapsulate in the map? When I went to see the source code of ECharts, the leader of party A did not know where to find a video:

But it’s something like this, where the shape of the stroke in the video is like an ELECTROcardiogram and then when you stroke the heart in the middle:

I don’t remember exactly, but either the one above or the one below:

At that time, the video is more dazzling than the above effects, but this “dazzling” but dazzling to their own head, there must be such an effect, how to communicate, people even said: we are willing to pay more!

But the money did not add in my here ah, into the boss’s pocket to go, the boss of course happy, let me have to do it.

He adds money, I work overtime…

SVG

But it’s safe to say that you can’t look at ECharts source code anymore. Mature open source projects like this have a lot of code and many libraries to rely on.

One by one to turn the source code to the horse month, and changed to this stroke effect to greatly change the source code to go, and finally may not be successful, so quickly gave up the idea.

Fortunately, I have good Canvas and SVG background, so stroke is the perfect effect for SVG.

But there was a huge problem:

  • Where can I find the SVG coordinates of Qingdao map?

Do you draw the coordinates yourself? Like Canvas’s map data?

So I found a map of Qingdao with stroke from the Internet:

I tried to trace it out in code, but I didn’t get more than a quarter of it before my eyes were gone. And compared with the picture, there is a certain visible error.

No, that’s too inefficient! There must be another way. Ask the company’s UI designer.

After they read it, they said: This is ok, you give me a picture of Qingdao, I will use AI(not artificial intelligence AI, but Adobe Illustrator) to draw it for you and export IT to SVG.

It took me a whole day to write the code, but it took me only half an hour to trace it, and the error was invisible to the naked eye:

After all, the exported image is only in SVG format, so to make it under the control of the program, we need to do a little more work:

<svg id="tsing-tao-map" data-name="tsing-tao-map" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 892 994">
  <defs>
    <defs>
      <filter id="filter" x="0" y="0" width="200%" height="200%">
        <feOffset result="offOut" in="SourceGraphic" dx="0" dy="2" />
        <feColorMatrix result="matrixOut" in="offOut" type="matrix"
        values=".15 0 0 0 0 0.15 0 0 0 0.15 0 0 0 0. />
        <feGaussianBlur result="blurOut" in="matrixOut" stdDeviation="1" />
        <feBlend in="SourceGraphic" in2="blurOut" mode="normal" />
      </filter>
    </defs>
  </defs>
  <polyline class="cls-1" points="428.5 668.5 429.5 668.5 429.5 672.5 430.5 672.5 430.5 676.5 429.5 676.5 429.5 677.5 426.5 679.5 427.5 679.5 429.5 682.5 429.5 684.5 431.5 686.5 431.5 690.5"/>
  <g class="cls-2">
    <polyline class="cls-3" points="328.75 65.13 330.5 67.5 334.5 67.5 336.5 66.5 337.5 64.5 339.5 64.5 342.5 66.5 343.5 69.5 343.5 73.5 344.5 74.5 348.5 74.5 351.5 71.5 355.5 71.5 355.5 69.5 363.5 69.5 369.5 73.5 370.5 74.5 371.5 75.5 371.5 76.5 369.5 79.5 364.5 80.5 364.5 81.5 360.5 81.5 360.5 83.5 359.5 83.5 359.5 87.5 363.5 91.5 364.5 91.5 364.5 92.5 369.5 92.5 369.5 92.5 369.5 92.5 369.5 92.5 369.5 92.5 369.5 92.5 369.5 91.5 370.5 91.5 371.5 88.5 374.5 88.5 374.5 89.5 376.5 91.5 378.5 91.5 378.5 90.5 382.5 90.5 383.5 91.5 383.5 93.5 384.5 93.5 384.5 94.5 383.5 94.5 379.5 96.5 378.5 97.5 376.5 99.5 374.5 100.5 374.5 103.5 381.5 113.5 382.5 114.5 382.5 119.5 381.5 119.5 381.5 121.5 377.5 127.5 376.5 128.5 376.5 130.5 375.5 130.5 375.5 133.5 374.5 135.5 373.5 138.5 138.5 370.5 141.5 367.5 141.5 364.5 143.5 363.5 144.5 362.5 142.5 145.5 362.5 148.5 363.5 148.5 364.5 151.5 366.5 152.5 368.5 155.5 370.5 159.5 370.5 161.5 368.5 161.5 368.5 164.5 367.5 164.5 366.5 167.5 366.5 171.5 365.5 171.5 365.5 179.5 364.5 180.5 364.5 185.5 363.5 185.5 363.5 190.5 192.5 192.5 362.5 195.5 361.5 195.5 361.5 197.5 360.5 197.5 360.5 201.5 359.5 206.5 359.5 209.5 357.5 212.5 357.5 214.5 356.5 214.5 355.5 218.5 354.5 218.5 354.5 221.5 354.5 232.5 355.5 232.5 355.5 236.5 357.5 238.5 357.5 240.5 356.5 240.5 356.5 243.5 248.5 246.5 359.5 249.5 360.5 253.5 256.5 360.5 257.5 360.5 261.5 359.5 261.5 359.5 268.5 359.5 282.5 360.5 283.5 360.5 289.5 361.5 290.5 362.5 292.5 362.5 295.5 363.5 296.5 365.5 298.5 368.5 299.5 370.5 301.5 371.5 303.5 371.5 307.5 370.5 308.5 369.5 310.5 369.5 314.5 368.5 314.5 367.5 320.5 365.5 321.5 363.5 322.5 360.5 322.5 360.5 321.5 357.5 321.5 357.5 323.5 356.5 323.5 356.5 355.5 355.5 355.5 355.5 359.5 351.5 329.5 349.5 329.5 349.5 327.5 345.5 327.5 345.5 326.5 342.5 326.5 337.5 330.5 333.5 330.5 332.5 331.5 332.5 327.5 337.5 326.5 340.5 326.5 342.5 327.5 342.5 327.5 349.5 323.5 352.5 319.5 355.5 318.5 356.5 314.5 356.5 310.5 359.5 308.5 359.5 308.5 358.5 306.5 358.5 304.5 363.5 304.5 368.5 303.5 368.5 303.5 368.5 303.5 303.5 371.5 302.5 371.5 301.5 376.5 298.5 381.5 297.5 383.5 297.5 385.5 298.5 385.5 305.5 393.5 306.5 393.5 306.5 398.5 304.5 398.5 304.5 404.5 308.5 410.5 309.5 410.5 309.5 417.5 310.5 417.5 310.5 418.5 313.5 419.5 314.5 419.5 314.5 419.5 313.5 425.5 313.5 426.5 308.5 426.5 308.5 425.5 304.5 425.5 304.5 427.5 303.5 427.5 303.5 433.5 301.5 435.5 298.5 435.5 298.5 436.5 296.5 436.5 296.5 437.5 294.5 439.5 294.5 445.5 296.5 446.5 446.5 305.5 446.5 306.5 447.5 306.5 450.5 308.5 450.5 308.5 455.5 305.5 455.5 302.5 459.5 302.5 467.5 300.5 470.5 300.5 471.5 301.5 471.5 301.5 476.5 302.5 476.5 302.5 479.5 305.5 483.5 309.5 483.5 316.5 487.5 317.5 487.5 317.5 491.5 319.5 492.5 323.5 492.5 323.5 494.5 324.5 494.5 324.5 494.5 495.5 326.5 496.5 329.5 496.5 329.5 497.5 330.5 497.5 332.5 498.5 332.5 500.5 331.5 501.5 331.5 503.5 330.5 503.5 330.5 503.5 330.5 510.5 327.5 510.5 327.5 514.5 326.5 514.5 326.5 515.5 54.5 515.5 324.5 515.5 324.5 54.5 518.5 322.5 518.5 321.5 521.5 320.5 521.5 319.5 524.5 316.5 527.5 314.5 527.5 314.5 532.5 308.5 537.5 308.5 541.5 301.5 541.5 301.5 543.5 294.5 549.5 293.5 550.5 290.5 550.5 286.5 552.5 286.5 555.5 287.5 288.5 557.5 289.5 559.5 289.5 560.5 288.5 560.5 288.5 564.5 286.5 564.5 284.5 561.5 284.5 559.5 283.5 559.5 282.5 562.5 282.5 562.5 281.5 563.5 281.5 568.5 282.5 569.5 282.5 574.5 284.5 575.5 284.5 582.5 281.5 582.5 280.5 582.5 280.5 583.5 281.5 584.5 281.5 585.5 281.5 585.5 283.5 586.5 283.5 587.5 286.5 587.5 286.5 586.5 288.5 586.5 288.5 587.5 289.5 589.5 289.5 590.5 286.5 590.5 284.5 592.5 284.5 595.5 286.5 596.5 289.5 599.5 289.5 595.5 291.5 595.5 293.5 598.5 293.5 601.5 288.5 601.5 286.5 603.5 286.5 606.5 288.5 607.5 291.5 609.5 294.5 612.5 295.5 614.5 296.66 615.37" 288.5 607.5 291.5 609.5 294.5 612.5 295.5 614.5 296.66 615.37"/>
    <polyline class="cls-3" ref="line2" points="235.5 419.97 237.5 419.5 237.5 416.5 238.5 415.5 239.5 415.5 243.5 419.5 244.5 420.5 247.5 247.5 416.5 250.5 416.5 255.5 423.5 255.5 424.5 259.5 424.5 259.5 422.5 262.5 419.5 266.5 419.5 266.5 417.5 267.5 416.5 270.5 416.5 270.5 417.5 275.5 417.5 275.5 418.5 278.5 418.5 279.5 419.5 280.5 419.5 281.5 417.5 282.5 417.5 282.5 418.5 418.5 283.5 418.5 283.5 419.5 285.5 419.5 285.5 416.5 287.5 416.5 290.5 414.5 291.5 414.5 291.5 416.5 292.5 416.5 292.5 417.5 296.5 417.5 296.5 419.5 303.5 419.5 303.5 420.5 306.5 420.5 306.5 307.5 422.5 310.5 422.5 310.5 426.5"/>
    <polyline class="cls-3" ref="line3" points="351.5 329.5 351.5 331.5 355.5 335.5 358.5 335.5 358.5 333.5 339.5 332.5 360.5 332.5 360.5 333.5 361.5 333.5 362.5 335.5 335.5 364.5 335.5 365.5 333.5 366.5 333.5 367.5 334.5 367.5 335.5 374.5 335.5 374.5 332.5 379.5 332.5 379.5 330.5 384.5 330.5 384.5 332.5 386.5 332.5 389.5 329.5 392.5 329.5 392.5 332.5 392.5 398.5 332.5 398.5 333.5 402.5 333.5 401.5 403.5 331.5 403.5 327.5 406.5 327.5 406.5 332.5 405.5 333.5 405.5 335.5 410.5 335.5 413.5 330.5 417.5 330.5 417.5 329.5 420.5 329.5 424.5 334.5 426.5 334.5 429.5 337.5 431.5 337.5 431.5 336.5 336.5 436.5 336.5 335.5 441.5 335.5 441.5 336.5 443.5 336.5 443.5 337.5 444.5 337.5 444.5 335.5 447.5 335.5 447.5 335.5 449.5 448.5 341.5 450.5 341.5 450.5 340.5 453.5 340.5 453.5 343.5 341.5 456.5 341.5 456.5 339.5 459.5 339.5 459.5 336.5 460.5 335.5 463.5 335.5 463.5 334.5 467.5 328.5 468.5 327.5 472.5 327.5 477.5 332.5 477.5 334.5 479.5 334.5 479.5 339.5 333.5 483.5 333.5 483.5 338.5 486.5 341.5 486.5 344.5 487.5 345.5 487.5 346.5 486.5 346.5 486.5 349.5 484.5 350.5 484.5 354.5 486.5 354.5 487.5 356.5 487.5 363.5 488.5 363.5 489.5 364.5 494.5 364.5 494.5 363.5 497.5 359.5 502.5 359.5 503.5 358.5 503.5 355.5 501.5 355.5 501.5 352.5 504.5 352.5 506.5 350.5 506.5 348.5 505.5 347.5 505.5 345.5 508.5 345.5 508.5 344.5 510.5 344.5 510.5 349.5 511.5 351.5 512.5 351.5 512.5 353.5 518.5 353.5 520.5 355.5 520.5 356.5 522.5 356.5 522.5 355.5 523.5 355.5 523.5 352.5 528.5 352.5 528.5 353.5 530.5 353.53"/>
    <polyline class="cls-3" points="331.93 498.21 334.5 496.5 334.5 492.5 333.5 492.5 333.5 478.5 331.5 478.5 332.5 475.5 336.5 472.5 337.5 472.5 336.5 477.5 339.5 478.5 343.5 479.5 344.5 481.5 345.5 480.5 346.5 479.5 349.5 479.5 349.5 482.5 350.5 484.5 350.5 491.5 346.5 492.5 346.5 493.5 350.5 493.5 350.5 494.5 494.5 494.5 492.5 497.5 353.5 498.5 357.5 498.5 357.5 500.5 362.5 500.5 362.5 504.5 367.5 510.5 371.5 513.5 372.5 514.5 374.5 514.5 374.5 508.5 378.5 508.5 378.5 507.5 384.5 507.5 385.5 509.5 391.5 509.5 391.5 517.5 395.5 522.5 399.5 522.5 399.5 522.5 399.5 527.5 400.5 528.5 400.5 529.5 403.5 529.5 403.5 523.5 404.5 523.5 405.5 525.5 407.5 525.5 411.5 518.5 413.5 513.5 519.5 415.5 519.5 422.5 509.5 422.5 505.5 416.5 502.5 416.5 416.5 498.5 417.5 494.5 421.5 494.5 422.5 497.5 422.5 501.5 427.5 502.5 427.5 508.5 433.5 508.5 437.5 511.5 443.5 511.5 448.5 508.5 508.5 452.5 508.5 452.5 512.5 452.5 519.5 456.5 519.5 520.5 459.5 520.5 461.5 517.5 466.5 517.5 466.5 519.5 468.5 519.5 468.5 519.5 468.5 517.5 471.5 517.5 471.5 515.5 470.5 515.5 470.5 513.5 475.5 513.5 476.5 511.5 479.5 511.5 482.5 519.5 485.5 520.5 489.5 520.5 489.5 514.5 487.5 513.5 488.5 510.5 490.5 510.5 497.5 518.5 502.5 518.5 503.5 520.5 505.5 520.5 505.5 518.5 518.5 510.5 518.5 510.5 519.5 519.5 519.5 520.5 521.5 523.5 521.5 523.5 513.5 526.5 510.5 527.5 510.5 528.5 511.5 530.5 511.5 530.5 522.5 542.5 522.5"/>
    <polyline class="cls-3" points="391.77 592.77 393.5 592.5 393.5 588.5 394.5 588.5 394.5 585.5 395.5 585.5 395.5 583.5 398.5 583.5 398.5 584.5 401.5 584.5 401.5 583.5 403.5 583.5 403.5 581.5 405.5 580.5 405.5 576.5 406.5 576.5 406.5 575.5 410.5 575.5 410.5 574.5 412.5 574.5 415.5 578.5 415.5 579.5 424.5 579.5 424.5 580.5 426.5 580.5 426.5 583.5 428.5 583.5 431.5 587.5 432.5 588.5 432.5 590.5 431.5 590.5 430.5 591.5 430.5 593.5 431.5 593.5 431.5 596.5 435.5 596.5 435.5 595.5 437.5 595.5 437.5 594.5 438.5 593.5 440.5 593.5 443.5 596.5 444.5 597.5 444.5 599.5 446.5 599.5 447.5 598.5 447.5 597.5 451.5 597.5 453.5 596.5 458.5 590.5 459.5 589.5 459.5 585.5 460.5 585.5 464.5 580.5 465.5 577.5 470.5 570.5 470.5 565.5 471.5 565.5 472.5 564.5 476.5 564.5 476.5 563.5 477.5 562.5 496.5 562.5 499.5 560.5 500.5 556.5 500.5 552.5 501.5 552.5 501.5 550.5 504.5 543.5 504.5 541.5 503.5 541.5 503.5 533.5 499.5 526.5 499.5 523.5 498.5 523.5 498.52 518.5"/>
    <polyline class="cls-3" points="459.35 589.65 462.5 589.5 462.5 590.5 464.5 592.5 470.5 592.5 472.5 472.5 472.5 594.5 472.5 472.5 472.5 596.5 471.5 596.5 471.5 598.5 470.5 599.5 470.5 605.5 468.5 607.5 468.5 612.5 463.5 615.5 463.5 618.5 462.5 618.5 462.5 621.5 457.5 625.5 455.5 625.5 451.5 627.5 444.5 634.5 433.5 634.5 433.5 433.5 636.5 425.5 643.5 425.5 645.5 428.5 648.5 431.5 654.5 434.5 661.5 435.5 663.5 663.5 435.5 664.5 431.5 664.5 428.5 666.5 428.5 668.5 424.5 668.5 423.5 668.5 423.5 669.5 420.5 669.5 420.5 669.5 420.5 668.5 412.5 668.5 412.5 670.5 407.5 670.5 406.5 671.5 406.5 674.5 405.5 674.5 405.5 679.5 404.5 679.5 404.5 404.5 680.5 402.5 681.5 402.5 682.5 400.5 682.5 400.5 681.5 399.5 680.5 390.5 680.5 389.5 680.5 388.5 678.5 386.5 678.5 386.5 679.5 679.5 384.5 680.5 680.5 381.5 680.5 381.5 678.5 379.5 678.5 379.5 679.5 379.5 378.5 679.5 674.44 675.56"/>
    <polyline class="cls-3" points="428.81 640.6 427.5 640.5 425.5 640.5 424.5 639.5 422.5 639.5 421.5 636.5 421.5 631.5 420.5 631.5 420.5 629.5 418.5 627.5 411.5 627.5 411.5 629.5 406.5 629.5 396.98 624.15"/>
    <polyline class="cls-3" points="96.5 699.15 98.5 699.5 98.5 701.5 102.5 701.5 102.5 703.5 104.5 703.5 104.5 708.5 105.5 705.5 105.5 709.5 108.5 709.5 108.5 713.5 110.5 713.5 112.5 711.5 114.5 711.5 115.5 713.5 117.5 714.5 117.5 717.5 122.5 717.5 122.5 718.5 718.5 126.5 718.5 126.5 715.5 127.5 714.5 127.5 709.5 131.5 705.5 133.5 705.5 133.5 705.5 133.5 707.5 138.5 707.5 138.5 708.5 142.5 708.5 142.5 708.5 142.5 706.5 145.5 702.5 145.5 700.5 146.5 699.5 146.5 697.5 144.5 694.5 146.5 692.5 150.5 692.5 151.5 691.5 153.5 691.5 153.5 692.5 155.5 692.5 160.5 687.5 165.5 687.5 167.5 691.5 170.5 693.5 170.5 696.5 173.5 694.5 175.5 693.5 693.5 179.5 693.5 179.5 692.5 184.5 689.5 186.5 689.5 186.5 690.5 188.5 690.5 188.5 688.5 189.5 687.5 192.5 687.5 192.5 686.5 201.5 686.5 206.5 681.5 211.5 681.5 214.5 679.5 216.5 679.5 216.5 681.5 217.5 684.5 219.5 684.5 222.5 681.5 222.5 678.5 223.5 676.5 223.5 674.5 222.5 673.5 222.5 670.5 220.5 669.5 220.5 667.5 222.5 667.5 221.5 229.5 671.5 229.5 673.5 229.5 673.5 230.5 673.5 230.5 668.5 233.5 668.5 237.5 235.5 663.5 234.5 663.5 234.5 657.5 233.5 656.5 232.5 655.5 228.5 655.5 228.5 654.5 232.5 654.5 232.5 654.5 232.5 653.5 235.5 653.5 234.5 650.5 234.5 650.5 234.5 648.5 235.5 646.5 237.5 646.5 237.5 642.5 234.5 642.5 234.5 637.5 235.5 635.5 235.5 633.5 240.5 633.5 243.5 637.5 248.5 637.5 249.5 636.5 250.5 635.5 254.5 635.5 256.5 637.5 256.5 638.5 261.5 638.5 262.5 636.5 264.5 636.5 275.5 643.5 279.5 643.5 282.98 644.5"/>
  </g>
  <polygon class="cls-4" points="655.5 477.5 655.5 478.5 656.5 478.5 656.5 479.5 657.5 657.5 657.5 657.5 657.5 657.5 657.5 655.5 657.5"/>
  <polygon class="cls-4" points="48.5 82.5 44.5 87.5 44.5 93.5 40.5 100.5 38.5 104.5 33.5 123.5 33.5 125.5 40.5 141.5 40.5 184.5 24.5 217.5 21.5 217.5 16.5 214.5 14.5 214.5 11.5 216.5 11.5 217.5 16.5 217.5 16.5 219.5 12.5 219.5 12.5 222.5 11.5 222.5 11.5 228.5 8.5 233.5 8.5 238.5 7.5 238.5 7.5 243.5 8.5 243.5 10.5 256.5 18.5 269.5 22.5 269.5 25.5 274.5 29.5 274.5 34.5 283.5 39.5 289.5 39.5 293.5 45.5 304.5 47.5 304.5 47.5 310.5 48.5 310.5 48.5 313.5 52.5 320.5 64.5 331.5 64.5 333.5 66.5 333.5 66.5 331.5 80.5 342.5 86.5 342.5 101.5 356.5 101.5 358.5 101.5 364.5 101.5 370.5 103.5 370.5 108.5 364.5 110.5 364.5 118.5 369.5 124.5 373.5 133.5 376.5 142.5 381.5 150.5 384.5 159.5 386.5 176.5 389.5 192.5 394.5 192.5 404.5 193.5 404.5 193.5 411.5 194.5 412.5 200.5 412.5 200.5 402.5 209.5 395.5 217.5 395.5 218.5 399.5 228.5 406.5 230.5 406.5 230.5 403.5 235.5 403.5 235.5 406.5 233.5 406.5 233.5 413.5 232.5 413.5 232.5 419.5 235.5 419.5 235.5 420.5 232.5 422.5 232.5 426.5 233.5 427.5 233.5 429.5 236.5 429.5 236.5 433.5 235.5 433.5 235.5 438.5 232.5 438.5 232.5 442.5 227.5 442.5 227.5 440.5 220.5 440.5 220.5 441.5 214.5 441.5 209.5 443.5 208.5 445.5 207.5 445.5 207.5 444.5 205.5 444.5 198.5 460.5 194.5 460.5 194.5 468.5 203.5 477.5 203.5 479.5 204.5 479.5 204.5 482.5 200.5 484.5 197.5 482.5 186.5 482.5 185.5 484.5 185.5 487.5 184.5 489.5 184.5 492.5 182.5 493.5 182.5 502.5 181.5 503.5 181.5 515.5 178.5 519.5 178.5 524.5 166.5 530.5 166.5 533.5 165.5 534.5 161.5 534.5 160.5 538.5 151.5 548.5 151.5 556.5 150.5 556.5 150.5 560.5 149.5 560.5 149.5 562.5 144.5 562.5 144.5 567.5 145.5 567.5 145.5 571.5 139.5 577.5 139.5 580.5 141.5 580.5 141.5 585.5 142.5 585.5 144.5 590.5 145.5 591.5 148.5 591.5 148.5 595.5 146.5 597.5 146.5 601.5 147.5 601.5 148.5 607.5 149.5 608.5 150.5 608.5 150.5 611.5 145.5 613.5 145.5 616.5 144.5 616.5 141.5 614.5 141.5 619.5 138.5 618.5 134.5 618.5 134.5 617.5 131.5 617.5 131.5 619.5 129.5 619.5 129.5 620.5 123.5 620.5 123.5 619.5 119.5 619.5 119.5 620.5 114.5 625.5 110.5 625.5 109.5 623.5 105.5 623.5 103.5 620.5 103.5 615.5 99.5 615.5 99.5 614.5 91.5 614.5 90.5 614.5 88.5 612.5 87.5 612.5 84.5 614.5 80.5 611.5 80.5 610.5 79.5 610.5 77.5 612.5 74.5 612.5 74.5 613.5 73.5 613.5 73.5 619.5 69.5 623.5 69.5 628.5 68.5 628.5 68.5 632.5 64.5 637.5 64.5 642.5 62.5 642.5 62.5 646.5 65.5 651.5 65.5 654.5 68.5 657.5 68.5 658.5 67.5 658.5 67.5 661.5 56.5 666.5 56.5 676.5 56.5 682.5 62.5 682.5 63.5 683.5 68.5 683.5 72.5 688.5 75.5 688.5 75.5 685.5 77.5 685.5 82.5 690.5 86.5 690.5 86.5 693.5 87.5 693.5 87.5 691.5 88.5 691.5 88.5 690.5 92.5 690.5 93.5 694.5 95.5 696.5 96.5 697.5 96.5 698.5 96.5 699.5 94.5 699.5 92.5 701.5 92.5 705.5 88.5 708.5 86.5 708.5 86.5 711.5 79.5 716.5 79.5 718.5 82.5 722.5 82.5 725.5 81.5 725.5 81.5 732.5 81.5 741.5 82.5 742.5 82.5 747.5 88.5 757.5 88.5 761.5 87.5 761.5 87.5 764.5 89.5 765.5 89.5 773.5 92.5 773.5 92.5 770.5 95.5 770.5 97.5 775.5 97.5 778.5 96.5 778.5 96.5 781.5 101.5 787.5 103.5 791.5 103.5 795.5 104.5 796.5 104.5 801.5 105.5 802.5 105.5 808.5 103.5 811.5 101.5 811.5 98.5 811.5 97.5 812.5 99.5 813.5 100.5 814.5 97.5 817.5 95.5 817.5 89.5 810.5 85.5 810.5 76.5 821.5 76.5 824.5 75.5 825.5 70.5 825.5 67.5 822.5 65.5 822.5 54.5 830.5 54.5 832.5 55.5 832.5 55.5 834.5 46.5 844.5 45.5 846.5 45.5 853.5 49.5 857.5 49.5 859.5 46.5 863.5 46.5 866.5 40.5 866.5 38.5 869.5 38.5 873.5 36.5 874.5 36.5 880.5 39.5 882.5 42.5 883.5 45.5 887.5 46.5 890.5 53.5 898.5 53.5 902.5 52.5 903.5 51.5 907.5 48.5 904.5 47.5 904.5 42.5 908.5 41.5 908.5 39.5 905.5 35.5 905.5 34.5 906.5 32.5 906.5 29.5 906.5 28.5 905.5 26.5 905.5 25.5 905.5 24.5 903.5 20.5 900.5 18.5 899.5 15.5 899.5 15.5 898.5 14.5 897.5 13.5 897.5 13.5 898.5 12.5 899.5 10.5 900.5 7.5 900.5 6.5 900.5 6.5 898.5 5.5 898.5 5.5 895.5 5.5 894.5 3.5 894.5 3.5 898.5 1.5 899.5 1.5 900.5 3.5 903.5 3.5 906.5 2.5 907.5 3.5 908.5 3.5 911.5 2.5 911.5 2.5 914.5 1.5 914.5 0.5 915.5 0.5 919.5 2.5 919.5 2.5 924.5 6.5 928.5 6.5 944.5 5.5 946.5 5.5 950.5 4.5 950.5 4.5 954.5 2.5 954.5 2.5 955.5 4.5 957.5 1.5 961.5 1.5 968.5 7.5 973.5 10.5 973.5 11.5 974.5 11.5 981.5 10.5 981.5 10.5 983.5 12.5 984.5 14.5 984.5 15.5 983.5 18.5 983.5 18.5 982.5 22.5 982.5 22.5 983.5 26.5 983.5 26.5 986.5 29.5 986.5 29.5 982.5 32.5 982.5 37.5 977.5 39.5 977.5 40.5 980.5 40.5 983.5 42.5 983.5 44.5 983.5 44.5 982.5 46.5 980.5 46.5 977.5 47.5 977.5 47.5 973.5 50.5 973.5 50.5 974.5 52.5 976.5 57.5 976.5 57.5 979.5 65.5 984.5 78.5 984.5 99.5 965.5 112.5 965.5 112.5 984.5 116.5 988.5 118.5 992.5 120.5 992.5 124.5 987.5 126.5 987.5 126.5 990.5 129.5 993.5 131.5 993.5 135.5 989.5 135.5 987.5 132.5 982.5 132.5 980.5 134.5 980.5 134.5 979.5 135.5 979.5 135.5 976.5 132.5 971.5 132.5 967.5 135.5 964.5 135.5 961.5 147.5 949.5 149.5 949.5 149.5 955.5 150.5 955.5 150.5 966.5 152.5 966.5 156.5 962.5 159.5 963.5 167.5 971.5 171.5 971.5 183.5 956.5 192.5 956.5 192.5 955.5 195.5 951.5 195.5 944.5 187.5 938.5 187.5 930.5 190.5 926.5 191.5 925.5 191.5 920.5 193.5 917.5 196.5 914.5 202.5 911.5 206.5 908.5 207.5 906.5 208.5 905.5 208.5 897.5 207.5 897.5 206.5 895.5 204.5 895.5 204.5 896.5 196.5 896.5 192.5 890.5 192.5 882.5 195.5 876.5 198.5 874.5 203.5 874.5 203.5 875.5 208.5 875.5 209.5 876.5 215.5 882.5 216.5 885.5 215.5 886.5 215.5 890.5 217.5 890.5 218.5 889.5 220.5 889.5 223.5 894.5 223.5 897.5 222.5 898.5 222.5 901.5 221.5 901.5 221.5 905.5 224.5 905.5 230.5 902.5 233.5 902.5 233.5 903.5 234.5 905.5 236.5 905.5 239.5 900.5 239.5 896.5 242.5 892.5 242.5 888.5 246.5 880.5 248.5 880.5 248.5 873.5 250.5 873.5 250.5 865.5 253.5 863.5 253.5 858.5 246.5 847.5 246.5 839.5 251.5 826.5 257.5 812.5 260.5 804.5 265.5 798.5 268.5 796.5 270.5 797.5 273.5 799.5 278.5 799.5 281.5 798.5 284.5 797.5 286.5 795.5 287.5 793.5 288.5 791.5 288.5 787.5 289.5 783.5 291.5 783.5 293.5 785.5 294.5 785.5 297.5 782.5 297.5 781.5 295.5 778.5 295.5 776.5 295.5 775.5 297.5 775.5 297.5 778.5 298.5 780.5 299.5 783.5 302.5 783.5 304.5 783.5 305.5 784.5 307.5 782.5 306.5 779.5 308.5 776.5 310.5 773.5 312.5 770.5 314.5 765.5 316.5 766.5 317.5 767.5 318.5 765.5 317.5 764.5 319.5 762.5 325.5 759.5 329.5 758.5 330.5 758.5 331.5 761.5 330.5 762.5 328.5 765.5 325.5 766.5 322.5 765.5 322.5 771.5 320.5 771.5 318.5 774.5 317.5 775.5 317.5 779.5 311.5 785.5 311.5 790.5 309.5 792.5 309.5 795.5 310.5 796.5 318.5 796.5 326.5 792.5 327.5 792.5 327.5 787.5 326.5 787.5 326.5 781.5 332.5 774.5 334.5 773.5 338.5 765.5 343.5 758.5 347.5 758.5 347.5 752.5 354.5 747.5 355.5 746.5 370.5 746.5 371.5 745.5 373.5 745.5 375.5 740.5 376.5 736.5 377.5 732.5 377.5 729.5 378.5 725.5 379.5 724.5 379.5 721.5 378.5 721.5 378.5 717.5 374.5 716.5 371.5 715.5 368.5 713.5 367.5 713.5 365.5 716.5 362.5 719.5 360.5 720.5 360.5 723.5 361.5 726.5 361.5 728.5 357.5 728.5 354.5 724.5 353.5 725.5 353.5 730.5 352.5 731.5 351.5 731.5 351.5 738.5 347.5 738.5 347.5 729.5 350.5 725.5 351.5 721.5 353.5 719.5 355.5 716.5 355.5 714.5 352.5 709.5 350.5 709.5 329.5 727.5 324.5 727.5 324.5 725.5 326.5 725.5 336.5 714.5 336.5 711.5 340.5 707.5 340.5 703.5 341.5 703.5 341.5 701.5 338.5 699.5 338.5 696.5 343.5 696.5 344.5 694.5 344.5 687.5 340.5 684.5 321.5 684.5 317.5 684.5 312.5 679.5 312.5 676.5 309.5 673.5 306.5 673.5 304.5 667.5 299.5 663.5 296.5 663.5 294.5 662.5 287.5 662.5 285.5 661.5 285.5 653.5 284.5 653.5 282.5 645.5 282.5 644.5 290.5 644.5 295.5 639.5 296.5 637.5 297.5 635.5 297.5 624.5 296.5 615.5 308.5 605.5 311.5 601.5 314.5 598.5 321.5 594.5 329.5 591.5 333.5 591.5 335.5 595.5 335.5 603.5 337.5 606.5 341.5 606.5 346.5 598.5 354.5 599.5 355.5 601.5 354.5 603.5 352.5 606.5 352.5 607.5 355.5 611.5 358.5 611.5 360.5 608.5 362.5 608.5 362.5 612.5 365.5 612.5 368.5 607.5 378.5 607.5 378.5 600.5 373.5 596.5 370.5 596.5 370.5 593.5 369.5 592.5 369.5 584.5 371.5 582.5 375.5 580.5 382.5 579.5 383.5 579.5 383.5 581.5 390.5 591.5 395.5 596.5 400.5 599.5 402.5 602.5 405.5 611.5 405.5 612.5 401.5 613.5 399.5 616.5 398.5 621.5 397.5 623.5 393.5 628.5 387.5 642.5 386.5 643.5 386.5 651.5 385.5 651.5 385.5 654.5 382.5 654.5 381.5 655.5 381.5 657.5 380.5 657.5 380.5 658.5 381.5 658.5 381.5 660.5 378.5 662.5 377.5 666.5 376.5 667.5 375.5 667.5 375.5 669.5 377.5 669.5 377.5 671.5 376.5 671.5 375.5 674.5 372.5 677.5 372.5 680.5 371.5 681.5 371.5 685.5 368.5 685.5 367.5 687.5 367.5 693.5 366.5 693.5 365.5 695.5 365.5 698.5 371.5 698.5 371.5 695.5 370.5 695.5 370.5 692.5 374.5 692.5 374.5 693.5 378.5 693.5 378.5 689.5 380.5 687.5 384.5 687.5 384.5 692.5 388.5 692.5 389.5 690.5 391.5 690.5 391.5 691.5 392.5 691.5 392.5 694.5 390.5 697.5 390.5 698.5 393.5 698.5 396.5 694.5 400.5 694.5 402.5 699.5 403.5 699.5 406.5 696.5 406.5 693.5 405.5 693.5 405.5 690.5 413.5 687.5 414.5 687.5 414.5 690.5 413.5 690.5 413.5 693.5 422.5 693.5 425.5 689.5 428.5 689.5 429.5 690.5 432.5 690.5 432.5 692.5 435.5 692.5 435.5 689.5 434.5 688.5 434.5 685.5 437.5 683.5 438.5 683.5 438.5 684.5 439.5 685.5 440.5 685.5 440.5 682.5 455.5 667.5 461.5 667.5 463.5 670.5 467.5 670.5 471.5 668.5 477.5 668.5 477.5 666.5 483.5 666.5 483.5 667.5 484.5 668.5 485.5 668.5 487.5 666.5 489.5 666.5 490.5 666.5 490.5 664.5 491.5 664.5 491.5 660.5 488.5 657.5 488.5 656.5 489.5 656.5 489.5 655.5 492.5 655.5 492.5 656.5 493.5 657.5 497.5 657.5 497.5 658.5 500.5 658.5 500.5 656.5 501.5 656.5 501.5 653.5 504.5 652.5 505.5 654.5 504.5 657.5 504.5 659.5 506.5 661.5 513.5 661.5 518.5 656.5 519.5 653.5 519.5 651.5 522.5 649.5 525.5 649.5 525.5 650.5 529.5 653.5 534.5 653.5 534.5 652.5 541.5 649.5 548.5 643.5 551.5 643.5 555.5 646.5 565.5 646.5 570.5 641.5 571.5 638.5 570.5 636.5 569.5 635.5 567.5 635.5 566.5 636.5 563.5 636.5 563.5 628.5 560.5 627.5 560.5 625.5 564.5 625.5 564.5 624.5 565.5 624.5 565.5 620.5 560.5 618.5 560.5 616.5 559.5 616.5 559.5 606.5 558.5 606.5 558.5 601.5 559.5 601.5 559.5 590.5 558.5 590.5 558.5 586.5 557.5 586.5 557.5 582.5 556.5 578.5 552.5 574.5 552.5 571.5 553.5 571.5 556.5 565.5 556.5 562.5 555.5 562.5 555.5 559.5 554.5 558.5 554.5 556.5 555.5 556.5 555.5 549.5 552.5 547.5 550.5 547.5 545.5 551.5 542.5 551.5 539.5 548.5 539.5 544.5 545.5 536.5 546.5 535.5 546.5 531.5 542.5 525.5 542.5 522.5 541.5 521.5 541.5 519.5 542.5 519.5 544.5 515.5 546.5 515.5 547.5 516.5 547.5 518.5 555.5 518.5 555.5 519.5 561.5 519.5 564.5 518.5 571.5 518.5 577.5 521.5 579.5 521.5 579.5 519.5 583.5 518.5 583.5 516.5 580.5 513.5 580.5 510.5 575.5 504.5 575.5 500.5 574.5 500.5 574.5 497.5 569.5 497.5 564.5 491.5 560.5 489.5 560.5 487.5 559.5 487.5 559.5 477.5 566.5 470.5 566.5 467.5 567.5 467.5 567.5 466.5 569.5 466.5 572.5 463.5 574.5 463.5 574.5 456.5 575.5 456.5 575.5 454.5 579.5 452.5 589.5 452.5 590.5 449.5 591.5 448.5 591.5 445.5 589.5 444.5 589.5 439.5 588.5 438.5 588.5 434.5 589.5 432.5 612.5 432.5 613.5 431.5 626.5 431.5 629.5 435.5 629.5 441.5 629.5 446.5 627.5 448.5 627.5 451.5 631.5 451.5 638.5 458.5 638.5 464.5 632.5 469.5 632.5 473.5 634.5 477.5 634.5 482.5 636.5 486.5 642.5 488.5 644.5 490.5 643.5 492.5 643.5 493.5 644.5 493.5 645.5 492.5 651.5 489.5 653.5 489.5 655.5 485.5 655.5 483.5 652.5 480.5 652.5 477.5 655.5 473.5 658.5 468.5 663.5 462.5 666.5 461.5 667.5 462.5 667.5 466.5 669.5 466.5 672.5 464.5 673.5 462.5 673.5 459.5 670.5 459.5 670.5 460.5 667.5 460.5 664.5 456.5 664.5 449.5 660.5 444.5 660.5 441.5 666.5 437.5 672.5 437.5 674.5 442.5 678.5 442.5 680.5 439.5 680.5 435.5 684.5 433.5 688.5 428.5 688.5 423.5 682.02 415.17 681.5 414.5 683.5 412.5 683.5 409.5 681.5 406.5 685.5 399.5 688.5 393.5 693.5 388.5 696.5 383.5 696.5 381.5 689.5 372.5 686.5 370.5 683.5 369.5 675.5 369.5 671.5 367.5 667.5 363.5 665.5 364.5 663.5 366.5 660.5 366.5 652.5 359.5 652.5 351.5 648.5 344.5 642.5 343.5 635.5 339.5 632.5 339.5 602.5 353.5 600.5 352.5 599.5 348.5 593.5 341.5 589.5 342.5 588.5 342.5 583.5 335.5 578.5 335.5 577.5 336.5 576.5 335.5 576.5 331.5 570.5 331.5 565.5 336.5 565.5 338.5 562.5 340.5 561.5 343.5 563.5 346.5 563.5 347.5 557.5 347.5 551.5 353.5 547.5 353.5 540.5 359.5 537.5 359.5 534.5 361.5 533.5 363.5 531.5 361.5 531.5 356.5 530.5 354.5 530.5 349.5 533.5 346.5 533.5 337.5 535.5 335.5 535.5 330.5 538.5 328.5 542.5 328.5 542.5 323.5 541.5 319.5 542.5 314.5 540.5 313.5 537.5 313.5 537.5 311.5 537.5 310.5 538.5 310.5 538.5 306.5 536.5 306.5 534.5 304.5 533.5 305.5 528.5 308.5 526.5 308.5 526.5 301.5 528.5 301.5 529.5 300.5 529.5 299.5 523.5 293.5 523.5 290.5 521.5 289.5 519.5 289.5 519.5 288.5 513.5 288.5 509.5 287.5 508.5 286.5 508.5 283.5 512.5 278.5 512.5 274.5 510.5 274.5 510.5 271.5 509.5 270.5 509.5 267.5 507.5 265.5 506.5 263.5 506.5 260.5 505.5 259.5 503.5 259.5 502.5 261.5 500.5 261.5 500.5 260.5 496.5 260.5 494.5 256.5 492.5 256.5 490.5 254.5 488.5 254.5 488.5 248.5 490.5 248.5 490.5 247.5 488.5 246.5 488.5 243.5 487.5 243.5 487.5 239.5 489.5 239.5 490.5 236.5 493.5 232.5 496.5 224.5 497.5 218.5 511.5 218.5 513.5 218.5 514.5 216.5 516.5 215.5 516.5 211.5 517.5 208.5 515.5 207.5 518.5 205.5 519.5 204.5 519.5 200.5 518.5 198.5 516.5 198.5 514.5 197.5 512.5 196.5 508.5 195.5 508.5 194.5 508.5 192.5 509.5 191.5 509.5 189.5 511.5 189.5 511.5 186.5 510.5 185.5 509.5 183.5 504.5 183.5 503.5 181.5 503.5 169.5 506.5 169.5 506.5 168.5 513.5 168.5 518.5 167.5 518.5 165.5 522.5 165.5 524.5 162.5 525.5 160.5 525.5 150.5 514.5 150.5 513.5 149.5 511.5 149.5 502.5 139.5 501.5 139.5 501.5 128.5 500.5 126.5 498.5 126.5 496.5 123.5 496.5 117.5 498.5 115.5 499.5 105.5 500.5 100.5 502.5 100.5 502.5 93.5 505.5 92.5 509.5 95.5 509.5 98.5 512.5 98.5 512.5 99.5 514.5 99.5 514.5 96.5 516.5 96.5 516.5 93.5 517.5 93.5 517.5 86.5 515.5 86.5 515.5 85.5 516.5 83.5 520.5 81.5 520.5 75.5 519.5 75.5 519.5 71.5 516.5 71.5 516.5 68.5 518.5 68.5 518.5 65.5 516.5 63.5 507.5 63.5 507.5 58.5 506.5 56.5 504.5 56.5 504.5 62.5 500.5 64.5 494.5 64.5 491.5 67.5 489.5 67.5 482.5 59.5 482.5 57.5 484.5 57.5 486.5 55.5 486.5 50.5 485.5 49.5 486.5 48.5 486.5 44.5 484.5 44.5 484.5 36.5 485.5 36.5 485.5 28.5 488.5 28.5 488.5 24.5 489.5 24.5 489.5 18.5 488.5 15.5 487.5 15.5 487.5 11.5 487.5 10.5 483.5 10.5 480.5 7.5 480.5 4.5 479.5 4.5 479.5 3.5 476.5 3.5 476.5 0.5 470.5 0.5 464.5 9.5 464.5 12.5 462.5 15.5 456.5 15.5 450.5 20.5 449.5 21.5 446.5 19.5 441.5 19.5 441.5 17.5 439.5 16.5 439.5 18.5 437.5 18.5 437.5 20.5 434.5 20.5 432.5 21.5 431.5 23.5 430.5 23.5 428.5 21.5 427.5 22.5 426.5 24.5 423.5 23.5 424.5 26.5 425.5 27.5 425.5 31.5 423.5 33.5 419.5 33.5 414.5 28.5 411.5 28.5 411.5 27.5 405.5 27.5 401.5 30.5 401.5 34.5 400.5 34.5 399.5 37.5 399.5 40.5 397.5 40.5 397.5 43.5 394.5 45.5 394.5 42.5 393.5 42.5 393.5 38.5 389.5 34.5 389.5 28.5 388.5 25.5 386.5 23.5 384.5 23.5 382.5 26.5 381.5 26.5 378.5 22.5 375.5 22.5 374.5 21.5 372.5 19.5 372.5 15.5 373.5 15.5 373.5 10.5 371.5 10.5 370.5 11.5 366.5 11.5 365.5 13.5 363.5 13.5 363.5 11.5 361.5 11.5 358.5 17.5 356.5 19.5 355.5 21.5 352.5 21.5 350.5 18.5 348.5 18.5 347.5 19.5 346.5 18.5 344.5 15.5 342.5 14.5 341.5 14.5 341.5 18.5 340.5 18.5 340.5 21.5 340.5 25.5 339.5 26.5 339.5 27.5 340.5 29.5 340.5 33.5 338.5 33.5 338.5 35.5 340.5 35.5 339.5 37.5 336.5 37.5 334.5 40.5 333.5 41.5 333.5 46.5 331.5 47.5 331.5 50.5 333.5 53.5 333.5 56.5 330.5 58.5 330.5 62.5 328.5 65.5 327.5 68.5 325.5 70.5 322.5 72.5 320.5 71.5 319.5 70.5 317.5 70.5 316.5 72.5 316.5 73.5 314.5 73.5 313.5 72.5 311.5 72.5 311.5 76.5 310.5 77.5 309.5 77.5 308.5 77.5 308.5 82.5 305.5 85.5 304.5 86.5 301.5 85.5 297.5 84.5 297.5 79.5 293.5 79.5 289.5 83.5 283.5 83.5 283.5 85.5 275.5 85.5 274.5 82.5 263.5 82.5 260.5 81.5 252.5 81.5 251.5 85.5 251.5 89.5 248.5 91.5 246.5 94.5 244.5 94.5 244.5 93.5 241.5 93.5 239.5 90.5 235.5 90.5 230.5 85.5 229.5 85.5 228.5 86.5 226.5 86.5 223.5 83.5 220.5 83.5 218.5 86.5 216.5 86.5 216.5 85.5 211.5 85.5 194.5 96.5 194.5 97.5 184.5 97.5 181.5 94.5 175.5 94.5 175.5 93.5 151.5 93.5 150.5 92.5 147.5 92.5 147.5 94.5 145.5 94.5 139.5 85.5 133.5 84.5 133.5 87.5 127.5 89.5 122.5 89.5 122.5 93.5 120.5 93.5 120.5 96.5 117.5 98.5 107.5 98.5 104.5 101.5 102.5 101.5 98.5 97.5 98.5 94.5 97.5 93.5 96.5 89.5 94.5 89.5 90.5 92.5 86.5 93.5 82.5 95.5 79.5 95.5 79.5 91.5 64.5 86.5 60.5 86.5 57.5 83.5 54.5 83.5 53.5 85.5 49.5 85.5 49.5 82.5 48.5 82.5"/>
  <polygon class="cls-4" points="311.5 859.5 310.5 865.5 306.5 871.5 303.5 877.5 303.5 883.5 308.5 888.5 312.5 888.5 320.5 881.5 321.5 877.5 317.5 872.5 317.5 868.5 316.5 867.5 316.5 859.5 311.5 859.5"/>
  <polygon class="cls-4" points="377.5 758.5 377.5 763.5 380.5 763.5 382.5 762.5 384.5 763.5 387.5 761.5 387.5 760.5 385.5 761.5 381.5 381.5 381.5 759.5 380.5 759.5 380.5 757.5 377.5 377.5 758.5"/>
  <polygon class="cls-4" points="465.5 748.5 463.5 748.5 463.5 749.5 744.5 751.5 467.5 751.5 467.5 748.5 465.5 748.5 465.5 465.5 748.5 465.5 748.5 748.5 465.5 748.5"/>
  <polygon class="cls-4" points="450.5 681.5 450.5 683.5 452.5 686.5 454.5 685.5 452.5 681.5 450.5 681.5 681.5"/>
  <polygon class="cls-4" points="505.5 664.5 505.5 667.5 506.5 668.5 509.5 668.5 509.5 669.5 510.5 669.5 512.5 667.5 509.5 664.5 509.5 662.5 507.5 662.5 507.5 664.5 505.5 664.5"/>
  <polygon class="cls-4" points="523.5 660.5 523.5 663.5 525.5 663.5 525.5 661.5 523.5 660.5"/>
  <line class="cls-4" x1="508.5" y1="727.5" x2="509.5" y2="728.5"/>
  <polygon class="cls-4" points="644.5 795.5 644.5 794.5 648.5 789.5 650.5 789.5 651.5 790.5 651.5 791.5 650.5 791.5 647.5 794.5 646.5 794.5 645.5 645.5 795.5 644.5 795.5"/>
  <polygon class="cls-4" points="679.5 610.5 679.5 612.5 680.5 613.5 682.5 613.5 682.5 611.5 681.5 610.5 679.5 610.5"/>
  <polygon class="cls-4" points="678.5 614.5 678.5 615.5 679.5 616.5 681.5 616.5 681.5 615.5 679.5 614.5 678.5 614.5"/>
  <polygon class="cls-4" points="594.5 574.5 594.5 578.5 593.5 578.5 593.5 581.5 596.5 584.5 598.5 584.5 599.5 583.5 599.5 581.5 598.5 580.5 598.5 579.5 597.5 579.5 597.5 574.5 594.5 574.5"/>
  <polygon class="cls-4" points="617.5 576.5 617.5 580.5 618.5 580.5 618.5 582.5 619.5 581.5 619.5 579.5 620.5 579.5 620.5 575.5 618.5 575.5 617.5 576.5 617.5 576.5"/>
  <polygon class="cls-4" points="576.5 582.5 576.5 580.5 579.5 579.5 580.5 579.5 580.5 579.5 580.5 581.5 578.5 581.5 577.5 581.5 576.5 582.5"/>
  <polygon class="cls-4" points="582.5 590.5 583.5 590.5 583.5 591.5 584.5 591.5 584.5 592.5 583.5 592.5 582.5 582.5 582.5 582.5 582.5 590.5 582.5 590.5 582.5 590.5"/>
  <polygon class="cls-4" points="571.5 543.5 571.5 547.5 570.5 547.5 540.5 548.5 572.5 549.5 573.5 549.5 574.5 548.5 574.5 543.5 543.5 571.5 543.5"/>
  <polygon class="cls-4" points="570.5 551.5 570.5 553.5 571.5 553.5 571.5 550.5 570.5 550.5 570.5 551.5"/>
  <polygon class="cls-4" points="635.5 488.5 634.5 490.5 634.5 491.5 637.5 493.5 639.5 493.5 639.5 490.5 637.5 488.5 635.5 488.5"/>
  <polygon class="cls-4" points="623.5 484.5 624.5 485.5 625.5 486.5 625.5 486.5 625.5 488.5 626.5 488.5 627.5 485.5 626.5 485.5 624.5 483.5 623.5 484.5"/>
  <polygon class="cls-4" points="670.5 471.5 671.5 471.5 671.5 671.5 468.5 672.5 468.5 672.5 467.5 673.5 467.5 673.5 465.5 675.5 465.5 676.5 467.5 676.5 467.5 676.5 468.5 674.5 468.5 673.5 469.5 673.5 471.5 672.5 472.5 670.5 472.5 670.5 471.5"/>
  <polygon class="cls-4" points="678.5 460.5 678.5 461.5 679.5 461.5 679.5 462.5 680.5 463.5 684.5 463.5 684.5 465.5 686.5 465.5 686.5 463.5 687.5 463.5 688.5 462.5 692.5 462.5 692.5 461.5 695.5 461.5 697.5 463.5 698.5 463.5 698.5 464.5 699.5 464.5 699.5 463.5 700.5 463.5 700.5 459.5 696.5 459.5 691.5 453.5 687.5 453.5 687.5 457.5 685.5 457.5 685.5 456.5 682.5 456.5 679.5 459.5 678.5 460.5"/>
  <polygon class="cls-4" points="709.5 448.5 709.5 449.5 708.5 449.5 708.5 449.5 709.5 450.5 709.5 451.5 709.5 453.5 711.5 453.5 712.5 452.5 712.5 450.5 711.5 450.5 711.5 448.5 711.5 447.5 709.5 447.5 709.5 448.5"/>
  <line class="cls-4" x1="709.5" y1="457.5" x2="710.5" y2="458.5"/>
  <polygon class="cls-4" points="697.5 415.5 697.5 418.5 698.5 418.5 698.5 418.5 698.5 419.5 699.5 419.5 700.5 418.5 701.5 418.5 705.5 417.5 705.5 417.5 705.5 417.5 705.5 417.5 705.5 417.5 705.5 416.5 704.5 415.5 703.5 414.5 702.5 414.5 701.5 415.5 700.5 415.5 699.5 414.5 698.5 414.5 697.5 415.5"/>
  <polygon class="cls-4" points="731.5 382.5 731.5 384.5 732.5 384.5 732.5 384.5 732.5 385.5 733.5 385.5 734.5 384.5 735.5 384.5 735.5 382.5 734.5 382.5 734.5 734.5 381.5 734.5 380.5 732.5 380.5 732.5 381.5 731.5 381.5 731.5 382.5"/>
  <polygon class="cls-4" points="887.5 553.5 887.5 557.5 888.5 557.5 888.5 557.5 888.5 558.5 889.5 559.5 890.5 559.5 891.5 558.5 557.5 890.5 890.5 555.5 889.5 889.5 553.5 887.5 553.5"/>
  <polygon class="cls-4" points="194.5 962.5 194.5 959.5 195.5 959.5 195.5 959.5 957.5 197.5 954.5 199.5 954.5 199.5 957.5 198.5 959.5 197.5 959.5 197.5 962.5 197.5 963.5 194.5 963.5 194.5 962.5"/>
  <polygon class="cls-4" points="154.5 967.5 154.5 970.5 155.5 970.5 155.5 971.5 157.5 971.5 157.5 971.5 157.5 970.5 157.5 969.5 155.5 969.5 155.5 969.5 969.5 155.5 967.5 154.5 967.5"/>
  <polygon class="cls-4" points="104.5 979.5 104.5 982.5 107.5 986.5 107.5 988.5 108.5 988.5 108.5 980.5 107.5 980.5 107.5 977.5 105.5 977.5 105.5 977.5 105.5 979.5 104.5 979.5"/>
</svg>
Copy the code

Don’t you get dizzy? It shows how ridiculous I thought I was to print this map in code. Just copy this code to your editor, save it as xxx.svg, and open it in your browser. This is what you’ll see:

Free release of Qingdao map code, if you have similar needs in front of the screen, I hope this code can help you.

Add animation

The vector map of Qingdao is not enough. After finishing the SVG code, we need to use the program to control the animation:

<template>
  <svg id="tsing-tao-map" ref="map" data-name="tsing-tao-map" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 892 994" @touchend="checkScale">
    <defs>
      <defs>
        <filter id="filter" x="0" y="0" width="200%" height="200%">
          <feOffset result="offOut" in="SourceGraphic" dx="0" dy="2" />
          <feColorMatrix result="matrixOut" in="offOut" type="matrix"
          values=".15 0 0 0 0 0.15 0 0 0 0.15 0 0 0 0. />
          <feGaussianBlur result="blurOut" in="matrixOut" stdDeviation="1" />
          <feBlend in="SourceGraphic" in2="blurOut" mode="normal" />
        </filter>
      </defs>
    </defs>
    <polyline class="cls-1" ref="line0" points=""/>
    <g class="cls-2">
      <polyline class="cls-3" ref="line1" points=""/>
      <polyline class="cls-3" ref="line2" points=""/>
      <polyline class="cls-3" ref="line3" points=""/>
      <polyline class="cls-3" ref="line4" points=""/>
      <polyline class="cls-3" ref="line5" points=""/>
      <polyline class="cls-3" ref="line6" points=""/>
      <polyline class="cls-3" ref="line7" points=""/>
      <polyline class="cls-3" ref="line8" points=""/>
    </g>
    <polygon class="cls-4" ref="line9" points=""/>
    <polygon class="cls-4" ref="line10" points=""/>
    <polygon class="cls-4" ref="line11" points=""/>
    <polygon class="cls-4" ref="line12" points=""/>
    <polygon class="cls-4" ref="line13" points=""/>
    <polygon class="cls-4" ref="line14" points=""/>
    <polygon class="cls-4" ref="line15" points=""/>
    <polygon class="cls-4" ref="line16" points=""/>
    <line class="cls-4" ref="line38" x1="" y1="" x2="" y2=""/>
    <polygon class="cls-4" ref="line17" points=""/>
    <polygon class="cls-4" ref="line18" points=""/>
    <polygon class="cls-4" ref="line19" points=""/>
    <polygon class="cls-4" ref="line20" points=""/>
    <polygon class="cls-4" ref="line21" points=""/>
    <polygon class="cls-4" ref="line22" points=""/>
    <polygon class="cls-4" ref="line23" points=""/>
    <polygon class="cls-4" ref="line24" points=""/>
    <polygon class="cls-4" ref="line25" points=""/>
    <polygon class="cls-4" ref="line26" points=""/>
    <polygon class="cls-4" ref="line27" points=""/>
    <polygon class="cls-4" ref="line28" points=""/>
    <polygon class="cls-4" ref="line29" points=""/>
    <polygon class="cls-4" ref="line30" points=""/>
    <line class="cls-4" ref="line39" x1="" y1="" x2="" y2=""/>
    <polygon class="cls-4" ref="line31" points=""/>
    <polygon class="cls-4" ref="line32" points=""/>
    <polygon class="cls-4" ref="line33" points=""/>
    <polygon class="cls-4" ref="line34" points=""/>
    <polygon class="cls-4" ref="line35" points=""/>
    <polygon class="cls-4" ref="line36" points=""/>
  </svg>
</template>

<script>
export default {
  data () {
    return {
      list: []
    }
  },
  mounted () {
    Object.entries(this.$refs).forEach(([k, v]) = > k.includes('line') && this.list.push(v))
    this.clearOffset(this.list)
  },
  methods: {
    clearOffset (list) {
      list.forEach(i= > {
        i.setAttribute('stroke-dasharray', i.getTotalLength())
        i.setAttribute('stroke-dashoffset', i.getTotalLength())
        setTimeout(() = > i.classList.contains('cls-4') && i.getTotalLength() > 100 && i.classList.add('no-offset'), 0)
        setTimeout(() = > i.classList.add('no-offset'), 6000)})}}</script>

<style lang="scss">
:root {
  background: black;
}
#tsing-tao-map {
  --stroke: white;
  --opacity:.8;
  --width: 1.2;
  height: 100vh;
  padding-left: 6vw;
  overflow: visible;
}
.cls-{&1, &3, &4 {
    fill: none;
    stroke: var(--stroke) { miterlimit: 10; width: var(--width) }
  }
  &1, &2 { opacity: var(--opacity) }
  &1, &2, &3 { stroke-width: calc(var(--width) * .8)}}.no-offset {
  transition: stroke-dashoffset 6s ease-in-out;
  stroke-dashoffset: 0
}
</style>
Copy the code

Wait, isn’t it not dependent on any framework or library? Why does this look so much like Vue code?

It’s true that this map and the rest are made in native SVG, but it wouldn’t seem intuitive to write pure JS to interact with SVG. To make things more intuitive, I’ve removed all the coordinate points from SVG. If you need to use them, you can copy them directly from the previous SVG code.

In fact, in this case, Vue is doing some pretty normal things

You can always change it to React, Angular, or even jQuery code, but Vue looks more intuitive when doing simple logic

Running result:

Because of the size of the gifs, they look like they’re one-card at a time, but they actually run smoothly on a computer (and the same goes for all the gifs that follow).

Although the stroke animation is written, there is another tricky problem: the coordinate system is gone!

Coordinate system conversion

What does it mean that the coordinates are gone? Because ECharts is also produced by Baidu, so the coordinate system of ECharts map is Baidu coordinate system, baidu search “Baidu coordinates”, the first appeared is Baidu pick coordinate system:

Where the mouse is placed, the corresponding coordinates of that position will appear, such as:

But SVG doesn’t have Baidu coordinates! If you think of SVG as an image, it will have a width and a height, right? The width is the x-coordinate, the height is the y-coordinate, and the width is the x-coordinate.

However, the current SVG image is a little large, zoom out and align it again:

That’s pretty much it, it’s not exactly right (the art pictures are a little bit wrong, they don’t exactly overlap), but you get the idea. Then give a border to see where the top left corner is:

This time know how to write the algorithm, the background is in accordance with the Baidu coordinate system point. It is the coordinate point of Baidu, you subtract it from the coordinate point of the upper left corner, you get the position relative to the upper left corner. Then multiply this image by the scale of the baidu map, and the algorithm is as follows:

location ([x, y]) {
      return [(x - 119.87) * 773, (37.13 - y) * 637.445]}Copy the code

Why is the x-coordinate x minus the upper-left x-coordinate, and then the y-coordinate becomes the upper-left y-coordinate minus y? (* x and y are the incoming coordinates *)

This is because the origin of Baidu map is not the top left corner of the world map, but the center of the world map:

So instead of having the origin in the top left corner of the computer, this is the plane cartesian coordinate system that we learned in high school. Still remember the famous Chinese thinker and writer Lu Xun once said:

  • Odd even doesn’t change the sign to look at the quadrant

Take a closer look, our country is in the first quadrant:

It’s going to get bigger and bigger, so it’s going to be the value that was passed in minus the top left corner. And the ordinate is just opposite to the computer coordinate system, the first quadrant is the further down the ordinate is smaller, the computer coordinate is the further down the ordinate is bigger. So I’m going to subtract the y-coordinate from the top left.

Of course, this algorithm is tailored to the Qingdao map I do, if you do the map of other regions, so as long as the upper left corner coordinates and picture proportion and then slightly change the value, the principle is the same.

The border becomes thinner as you zoom in

Although SVG is a vector image, zoom in and out without distortion, but the border of the map will also zoom in:

This doesn’t look so good, so let’s add a touchend event:

<template>
  <svg ref="map" @touchend="checkScale"></svg>
</template>

<script>
import Panzoom from '@panzoom/panzoom'
  
export default {
  data () {
  	panzoom: null.list: []
  },
  mounted () {
  	Object.entries(this.$refs).forEach(([k, v]) = > k.includes('line') && this.list.push(v))
    this.clearOffset(this.list)
  	this.panzoom = Panzoom(this.$refs.map, { minScale: 1.maxScale: 100})},methods: {
    clearOffset (list) {
        list.forEach(i= > {
          i.setAttribute('stroke-dasharray', i.getTotalLength())
          i.setAttribute('stroke-dashoffset', i.getTotalLength())
          setTimeout(() = > i.classList.contains('cls-4') && i.getTotalLength() > 100 && i.classList.add('no-offset'), 0)
          setTimeout(() = > i.classList.add('no-offset'), 6000)
        })
      }
    },
  	checkScale () {
      const scale = this.panzoom.getScale()
  	  const map = this.$refs.map
  
      if (scale > 36) {
        map.setAttribute('style', map.getAttribute('style') + '--width: .02; ')}else if (scale > 25) {
        map.setAttribute('style', map.getAttribute('style') + '--width: .05; ')}else if (scale > 16) {
        map.setAttribute('style', map.getAttribute('style') + '--width: .1; ')}else if (scale > 6) {
        map.setAttribute('style', map.getAttribute('style') + '--width: .2; ')}else if (scale > 2) {
        map.setAttribute('style', map.getAttribute('style') + '--width: .5; ')}else if (scale > 1.2) {
        map.setAttribute('style', map.getAttribute('style') + '--width: 1; ')}else {
        map.setAttribute('style', map.getAttribute('style') + '-- width: 1.2; ')}}}}</script>
Copy the code

The effect is as follows:

So this –width is the CSS variable, so if you don’t know what a CSS variable is you can click on the CSS variable link.

Add coordinates

We randomly find some points in Qingdao in the coordinate pickup system and put them into the data to simulate the data sent from the background:

<template>
  <svg ref="map" @touchend="checkScale">
  	<! Just put the new code at the end of the SVG tag -->
    <template v-for="(i, j) of points">
      <circle class="point" :cx="i[0]" :cy="i[1]" :r="pointStyle.size" :key="`point${j}`"
        :fill="pointStyle.color" :stroke="pointStyle.border.color" :stroke-width="pointStyle.border.width"
      />
      <text :key="`txt${j}`" :x="i[0]" :y="i[1] - 18" class="txt">{{i[2]}}</text>
    </template>
  </svg>
</template>

<script>
import Panzoom from '@panzoom/panzoom'
  
export default {
  data () {
  	panzoom: null.list: [].pointStyle: {
      size: 10.color: 'rgb(255, 66, 88)'.border: { width: 2.color: 'rgb(255, 255, 255)'}},pointsData: [{
      id: 0.title: 'China XX Company'.point: [120.111.36.8003] {},id: 1.title: 'Shandong XX Company'.point: [120.094693.35.928573] {},id: 2.title: 'Qingdao XX Company'.point: [120.459023.36.399622]
    }]
  },
  mounted () {
  	Object.entries(this.$refs).forEach(([k, v]) = > k.includes('line') && this.list.push(v))
    this.clearOffset(this.list)
  	this.panzoom = Panzoom(this.$refs.map, { minScale: 1.maxScale: 100})},methods: {
    clearOffset (list) {
        list.forEach(i= > {
          i.setAttribute('stroke-dasharray', i.getTotalLength())
          i.setAttribute('stroke-dashoffset', i.getTotalLength())
          setTimeout(() = > i.classList.contains('cls-4') && i.getTotalLength() > 100 && i.classList.add('no-offset'), 0)
          setTimeout(() = > i.classList.add('no-offset'), 6000)
        })
      }
    },
  	checkScale () {
      const scale = this.panzoom.getScale()
  	const map = this.$refs.map
  
      if (scale > 36) {
        map.setAttribute('style', map.getAttribute('style') + '--width: .02; ')}else if (scale > 25) {
        map.setAttribute('style', map.getAttribute('style') + '--width: .05; ')}else if (scale > 16) {
        map.setAttribute('style', map.getAttribute('style') + '--width: .1; ')}else if (scale > 6) {
        map.setAttribute('style', map.getAttribute('style') + '--width: .2; ')}else if (scale > 2) {
        map.setAttribute('style', map.getAttribute('style') + '--width: .5; ')}else if (scale > 1.2) {
        map.setAttribute('style', map.getAttribute('style') + '--width: 1; ')}else {
        map.setAttribute('style', map.getAttribute('style') + '-- width: 1.2; ')}}},computed: {
    points () {
      return this.pointsData.map(({ point: [x, y], title }) = > [(x - 119.87) * 773, (37.13 - y) * 637.445, title])
    }
  }
}
</script>

<style lang="scss">
:root {
  background: black;
}
#tsing-tao-map {
  --stroke: white;
  --opacity:.8;
  --width: 1.2;
  height: 100vh;
  padding-left: 6vw;
  overflow: visible;
}
.cls-{&1, &3, &4 {
    fill: none;
    stroke: var(--stroke) { miterlimit: 10; width: var(--width) }
  }
  &1, &2 { opacity: var(--opacity) }
  &1, &2, &3 { stroke-width: calc(var(--width) * .8)}}.no-offset {
  transition: stroke-dashoffset 6s ease-in-out;
  stroke-dashoffset: 0
}
.txt {
  stroke: white { width: .6 }
  fill: none;
  filter: url(#filter);
  text: { anchor: middle }
  font: { size: 18px; weight: bold }
}
.point..txt {
  animation: show-points 1s 12s both;
}
@keyframes show-points {
  from {
  	transform: translateY(-10%);
    opacity: 0;
    pointer-events: none
  }
  to {
    opacity: 1;
    pointer-events: auto; }}</style>
Copy the code

Running result:

Of course, I haven’t written down the logic of zooming in and out of the map, because this logic is similar to stroke zooming in and out of the map, so I’m not going to waste any space here.

Then you just need to add the click event in the < Circle > tag, and then do the logic you want to do, let’s see the click effect of Qingdao Bank:

There’s no data in it, so it’s an empty board.

conclusion

Isn’t that cool? Although this blog is a map of Qingdao, the idea is the same. If you have a requirement to make another map, follow my steps:

  • Start by finding a map with a stroke on the Internet
  • Ask the artist to follow it with AI
  • Export vector drawings in SVG format
  • Open it with an editor and you’ll see the code
  • Use JS and CSS to control SVG
  • Write a coordinate transformation algorithm
  • When zooming in, stroke and coordinate points should be dynamically zoomed out

The project of Bank of Qingdao is not just this one, it’s almost everywhere. I’ll show you a few giFs:

You can leave a comment on which effects you like, and I’ll post a blog post if one is of particular interest.

Past excellent articles:

  • Microsoft launches comments section on GitHub
  • Vue 3.0.3: New CSS variable passing and the latest Ref Proposal
  • You Yuxi: Ref Grammar Sugar Proposal
  • “Double 11 small black box is cool? Let’s use CSS variables to improve!”
  • “Don’t underestimate the nine grid, one question can let a candidate reveal his true colors!”
  • “Mobile Layout Interview Questions to test your CSS Skills (Center)”
  • A series of confusing behaviors after setting prototype Objects as Proxies
  • A fun new feature of Vue: Introducing JS variables into CSS
  • Vue’s Super Fun New Feature: DOM Portal
  • “Use of React’s Super-popular CSS-in-JS Library in the Vue Project: Styled – Components”
  • Is It Finally Vue’s Turn to Inspire React?
  • A Small Pit in Vue3 on IOS
  • Upgrade your React project to Immer instead of Immutable by 2020
  • “Soul Interrogation from the Author of React Hooks and Immutable”
  • Good news, Vue3 official document is available in Chinese!
  • Hooks use of the New VUe-Router
  • Vue 3:20 Years of Status Updates
  • React 17 is officially a transition version!
  • Yu Yuxi: The Design Process of Vue3
  • The Father of Node’s refactoring Deno is finally released. Will it Replace Node after all?
  • The Vue3 beta was released early this morning and openly supports scaffolding!