vydimitrov / react-countdown-circle-timer

Lightweight React/React Native countdown timer component with color and progress animation based on SVG

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

The usage and remaining radians are inconsistent

1280103995 opened this issue · comments

commented
<CountdownCircleTimer
  strokeLinecap={"square"}
  duration={100}
  initialRemainingTime={90}
  colors={[["#004777", 0.33], ["#F7B801", 0.33], ["#A30000"]]}
/>


<CountdownCircleTimer
  strokeLinecap={"square"}
  duration={100}
  initialRemainingTime={10}
  colors={[["#004777", 0.33], ["#F7B801", 0.33], ["#A30000"]]}
/>

I just modified the demo in the readme.

Is this a bug or by design, or am I missing some properties? Anyway, thanks a lot for your library.

Hey @1280103995, yup, this is how the timer is supposed to work. You set the duration of 100 so the full circle will be 100 seconds. Now you want to change the start point and pass initialRemainingTime of 90 seconds. So now when the timer renders it will start from a point where 90 seconds are left.

Check also this one, it may help you to understand the logic.

commented

I mean: in pic 1, the arc length in grey should be equal to the arc length in red (it seems) in pic 2.

The initialRemainingTime determines the arc length in red when the component mounts.

commented

When I change the code to (1 remaining):

<div
  className="timer-wrapper"
  style={{ justifyContent: "center", alignItems: "center" }}
  >
    <CountdownCircleTimer
      strokeLinecap={"square"}
      duration={100}
      initialRemainingTime={1}
      colors={[["#004777", 0.33], ["#F7B801", 0.33], ["#A30000"]]}
    />
    <div
       style={{
          height: "100%",
          width: 1,
          backgroundColor: "pink",
          position: "absolute"
       }}
    />
</div>

The effect obtained is as follows:

It seems that some arc length is added.

Is this a bug in SVG?

I see, so your concern is that small piece on the right side of the pink line?

commented

Yes. But there is also on the left.

The part on the left is the remaining time that you pass with initialRemainingTime={1}, This is 1 second left from the 100 seconds you pass as duration.

commented

So the correct effect should be: in the case of the remaining 1, only draw a little arc length to the left of the pink line.

commented

I've been troubleshooting all day today, it should be an SVG bug, I'll continue tomorrow.

So the correct effect should be: in the case of the remaining 1, only draw a little arc length to the left of the pink line.

Yes, that is correct. At this moment, I do not have any clue why it move a bit to the right. I will try to investigate it. Is this critical issue for you? This is really the first time I see it.

I think I found it, the path starting point needs to be moved with half of the width of the path. Like so

Before d="m 90,6 a 84,84 0 1,0 0,168 a 84,84 0 1,0 0,-168"
After d="m 84,6 a 84,84 0 1,0 0,168 a 84,84 0 1,0 0,-168"

At first look it seems that to fix it we will need a custom path for the circle and not using arches as above, which I am not sure it is worth doing it.

commented

So the correct effect should be: in the case of the remaining 1, only draw a little arc length to the left of the pink line.

Yes, that is correct. At this moment, I do not have any clue why it move a bit to the right. I will try to investigate it. Is this critical issue for you? This is really the first time I see it.

The problem exists in my production app, but it doesn't affect much. Just a UI issue.

commented

I tried to implement the same progress bar using react-native-svg, same problem.

Yup, it is the same logic to render the path. I am not sure if I am going to fix it since it is very tricky. If that is such a big problem one idea is to rotate the path so it matches the start point.

I will check if I can come up with some formula to calculate the start point and the arches based on the path width but can't promises anything.

Here is a workaround you can use for now. https://codesandbox.io/s/busy-brook-3fmyz?file=/src/index.js

The angle that we rotate the path to match the start very much depends of the stroke width. So this is not a solution that is going to work in every case.

React.useEffect(() => {
    document.querySelectorAll("path")[1].style.transform =
      "translate(90px, 90px) rotate(-4deg) translate(-90px, -90px)";
  }, []);
commented

This method is great, thank you for your work.

I would like to know why their arc lengths are different when the initialRemainingTime is 1 and when it is 99. :)

The arch lengths is the same - you can read more on how the animation works here - https://css-tricks.com/svg-line-animation-works/

commented

I'm not good at using svg, but I'll learn it later.


In fact, I use this component as a progress bar.

As you can see from the picture, in the left picture, the gray arc length is less than the navy blue arc length in the right picture.

Since their arc lengths are both 10, the lengths should be equal. That's what I'm asking about this issue.

Ooo now I see what you mean... this is very interesting... I will try to dig in the code to see if I can figure out why is that. The function that calculates the arch is the same.

I guess it has something to do with the fact that we rotated the path. Check here without rotation. In both cases seems symmetrical. https://codesandbox.io/s/busy-brook-3fmyz?file=/src/index.js

image
image

commented

How can I modify an svg so with "square" stroke it's starts(ends) at the "12 o'clock" instead of being exceeded to the right?
This lead to noticeable lag in visual start of the timer's circle in case of "square" option for stroke(

@NWPoul, did you see this one? #190 (comment)

commented

@NWPoul, did you see this one?

Yes but thought it was about the arc length
and all what I managed to achieve with it - is shifting circle from it's starting ponits... I am not strong with SVG😇

You will need just to add the one below to your timer component and adjust the rotation angle based on the strokeWdith and may be the translate style, which is half of the size prop you pass to the component, by default it is 180.

React.useEffect(() => {
    document.querySelectorAll("path")[1].style.transform =
      "translate(90px, 90px) rotate(-4deg) translate(-90px, -90px)";
  }, []);
commented

You will need just to add the one below to your timer component and adjust the rotation angle based on the strokeWdith and may be the translate style, which is half of the size prop you pass to the component, by default it is 180.

Thank you for the answer!
Yes, after ajusting "translate" parameter the circle don't shift aside,
but now the stroke starts mooving from the point exeeded to the left from "12:00" point... so the lag is still there...
besides that, the start line now tilted relative to vertical axis(
image

commented

UPD:
After RTFM for SVG
mine (and probably others) problem solution is easy - just set "butt" for stroke-linecap prop)

image

@NWPoul this is genius... I really did not think about it. This really solved the problem. It seems I will need to extend the strokeLinecap prop type to support butt so TS is happy.

butt option was added in v3.0.8. @1280103995 please test it and let me know if we can close the bug.

I am closing this one. Let me know if you have any further questions.

commented

sorry I'm late. I took a long vacation.

Now v3.0.8 solved my problem.

@NWPoul @vydimitrov Thank you so much!