vydimitrov / react-countdown-circle-timer

Lightweight React/React Native countdown timer component with color and progress animation based on SVG
MIT License
692 stars 87 forks source link

The usage and remaining radians are inconsistent #190

Closed 1280103995 closed 2 years ago

1280103995 commented 2 years ago
<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.

vydimitrov commented 2 years ago

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.

1280103995 commented 2 years ago

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

vydimitrov commented 2 years ago

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

1280103995 commented 2 years ago

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?

vydimitrov commented 2 years ago

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

1280103995 commented 2 years ago

Yes. But there is also on the left.

vydimitrov commented 2 years ago

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.

1280103995 commented 2 years ago

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.

1280103995 commented 2 years ago

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

vydimitrov commented 2 years ago

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.

vydimitrov commented 2 years ago

Preproduction demo here - https://codesandbox.io/s/busy-brook-3fmyz?file=/src/index.js

vydimitrov commented 2 years ago

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.

1280103995 commented 2 years ago

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.

1280103995 commented 2 years ago

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

vydimitrov commented 2 years ago

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.

vydimitrov commented 2 years ago

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)";
  }, []);
1280103995 commented 2 years ago

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. :)

vydimitrov commented 2 years ago

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

1280103995 commented 2 years ago

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.

vydimitrov commented 2 years ago

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.

vydimitrov commented 2 years ago

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

NWPoul commented 2 years ago

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(

vydimitrov commented 2 years ago

@NWPoul, did you see this one? https://github.com/vydimitrov/react-countdown-circle-timer/issues/190#issuecomment-1014221159

NWPoul commented 2 years ago

@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😇

vydimitrov commented 2 years ago

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)";
  }, []);
NWPoul commented 2 years ago

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

NWPoul commented 2 years ago

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

image

vydimitrov commented 2 years ago

@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.

vydimitrov commented 2 years ago

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

vydimitrov commented 2 years ago

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

1280103995 commented 2 years ago

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

Now v3.0.8 solved my problem.

@NWPoul @vydimitrov Thank you so much!