使用css - circle进度条逐步创建和填充弧

时间:2017-12-20 16:06:53

标签: html css css3 animation progress-bar

我正在努力填补像进度条一样的弧线,因为我在使用CSS时效果不佳。

我希望实现"进步"像这样: enter image description here

我偶然发现了这个:https://codepen.io/enslavedeagle/pen/AXzaKE

#arc,
#arc::before {
  display: block;
  box-sizing: border-box;
  border-radius: 100%;
  width: 100px;
  height: 100px;
  position: absolute;
  background-color: transparent;
  padding: 0;
  margin: 0;
}

#arc {
  border: solid #00BBEE 12px;
  clip: rect(0px, 100px, 50px, 0px);
  margin: 25px;
}

#arc::before {
  content: '';
  border: solid black 12px;
  top: -12px;
  left: -12px;
  clip: rect(0px, 100px, 50px, 0px);
  transform: rotate(-150deg);
  /* define the fill length, using the rotation above.
     from -180deg (0% fill) to 0deg (100% fill) */
  /* if you have a better solution to make thing like this 
     work, please let me know! :) */
}

并尝试自定义为我想要的但是直到现在还没有成功:在这里:https://codepen.io/anon/pen/qpNrEP

任何人都可以提供一些帮助吗?也可以替代解决方案来实现这一目标。

我很欣赏

亲切的问候,

5 个答案:

答案 0 :(得分:1)

您可以在另一个上面使用带有两个弧的SVG,然后使用stroke-dash-array

svg {
  height: 90vh;
  margin: auto;
  display: block;
}

path {
  stroke-linecap: round;
  stroke-width: 2;
}

path.grey {
  stroke: lightgrey;
}

path.purple {
  stroke: purple;
  stroke-dasharray: calc(40 * 3.142 * 1.85);
  stroke-dashoffset: 20;
  /* adjust last number for variance */
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewbox="0 0 100 100">
    <path class="grey" d="M40,90
             A40,40 0 1,1 60,90"
          style="fill:none;"/>
    <path class="purple" d="M40,90
             A40,40 0 1,1 60,90"
          style="fill:none;"/>
</svg>

答案 1 :(得分:1)

使用 SVG 是创建这样的弧的最佳方式。 这是加载器所有迭代的解决方案:

.progress-wrapper {
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: space-around;
}

path {
  stroke-linecap: round;
  stroke-width: 6;
}

.grey {
  stroke: #e5e5e5;
}

.red {
  stroke: #e33800;
  stroke-dasharray: 248;
  stroke-dashoffset: 240;
  /* adjust last number for variance */
}

.red-02 {
  stroke-dashoffset: 220;
}

.red-03 {
  stroke-dashoffset: 200;
}

.red-04 {
  stroke-dashoffset: 180;
}

.red-05 {
  stroke-dashoffset: 160;
}

.red-06 {
  stroke-dashoffset: 140;
}

.red-07 {
  stroke-dashoffset: 120;
}

.red-08 {
  stroke-dashoffset: 100;
}

.red-09 {
  stroke-dashoffset: 50;
}

.red-10 {
  stroke-dashoffset: 0;
}
<div class="progress-wrapper">
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
      <path class="grey" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
      <path class="red" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
  </svg>
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
      <path class="grey" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
      <path class="red red-02" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
  </svg>
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
      <path class="grey" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
      <path class="red red-03" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
  </svg>
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
      <path class="grey" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
      <path class="red red-04" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
  </svg>
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
      <path class="grey" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
      <path class="red red-05" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
  </svg>
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
      <path class="grey" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
      <path class="red red-06" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
  </svg>
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
      <path class="grey" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
      <path class="red red-07" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
  </svg>
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
      <path class="grey" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
      <path class="red red-08" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
  </svg>
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
      <path class="grey" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
      <path class="red red-09" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
  </svg>
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="37 -5 120 100" width="120" height="100">
      <path class="grey" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
      <path class="red red-10" d="M55,90
               A55,55 0 1,1 140,90"
            style="fill:none;"/>
  </svg>
</div>

https://codepen.io/shalinigandhi/pen/mdmmwdV

答案 2 :(得分:0)

这是一个使用SVG创建循环进度条的Angular模块。看起来正是您正在寻找的。

回购: https://github.com/crisbeto/angular-svg-round-progressbar

演示: http://crisbeto.github.io/angular-svg-round-progressbar/

答案 3 :(得分:0)

我刚刚在Angular 2中创建了一个plnker,我认为这正是你想要的。

它用变量管理第二个弧的填充:

this.percentPath=(233-(V*2.33)); //233 is the maximun number stroke-dashoffset needs to disapear the second path 

然后,在组件中我调用一个函数,该函数从min = 0和max = 100的滑块中获取值:

private static final String TAG = "EmailPassword";

private TextView mStatusTextView;
private TextView mDetailTextView;
private EditText mEmailField;
private EditText mPasswordField;

// [START declare_auth]
private FirebaseAuth mAuth;
// [END declare_auth]

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.auth_email_password);

    // Views
    mStatusTextView = findViewById(R.id.status);
    mDetailTextView = findViewById(R.id.detail);
    mEmailField = findViewById(R.id.field_email);
    mPasswordField = findViewById(R.id.field_password);

    // Buttons
    findViewById(R.id.email_sign_in_button).setOnClickListener(this);
    findViewById(R.id.email_create_account_button).setOnClickListener(this);
    findViewById(R.id.sign_out_button).setOnClickListener(this);
    findViewById(R.id.verify_email_button).setOnClickListener(this);

    // [START initialize_auth]
    mAuth = FirebaseAuth.getInstance();
    // [END initialize_auth]
}

// [START on_start_check_user]
@Override
public void onStart() {
    super.onStart();
    // Check if user is signed in (non-null) and update UI accordingly.
    FirebaseUser currentUser = mAuth.getCurrentUser();
    updateUI(currentUser);
}
// [END on_start_check_user]

private void createAccount(String email, String password) {
    Log.d(TAG, "createAccount:" + email);
    if (!validateForm()) {
        return;
    }

    showProgressDialog();

    // [START create_user_with_email]
    mAuth.createUserWithEmailAndPassword(email, password)
            .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        // Sign in success, update UI with the signed-in user's information
                        Log.d(TAG, "createUserWithEmail:success");
                        FirebaseUser user = mAuth.getCurrentUser();
                        updateUI(user);
                    } else {
                        // If sign in fails, display a message to the user.
                        Log.w(TAG, "createUserWithEmail:failure", task.getException());
                        Toast.makeText(EmailAuthActivity.this, "Authentication failed.",
                                Toast.LENGTH_SHORT).show();
                        updateUI(null);
                    }

                    // [START_EXCLUDE]
                    hideProgressDialog();
                    // [END_EXCLUDE]
                }
            });
    // [END create_user_with_email]
}

private void signIn(String email, String password) {
    Log.d(TAG, "signIn:" + email);
    if (!validateForm()) {
        return;
    }

    showProgressDialog();

    // [START sign_in_with_email]
    mAuth.signInWithEmailAndPassword(email, password)
            .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        // Sign in success, update UI with the signed-in user's information
                        Log.d(TAG, "signInWithEmail:success");
                        FirebaseUser user = mAuth.getCurrentUser();
                        updateUI(user);
                    } else {
                        // If sign in fails, display a message to the user.
                        Log.w(TAG, "signInWithEmail:failure", task.getException());
                        Toast.makeText(EmailAuthActivity.this, "Authentication failed.",
                                Toast.LENGTH_SHORT).show();
                        updateUI(null);
                    }

                    // [START_EXCLUDE]
                    if (!task.isSuccessful()) {
                        mStatusTextView.setText(R.string.auth_failed);
                    }
                    hideProgressDialog();
                    // [END_EXCLUDE]
                }
            });
    // [END sign_in_with_email]
}

private void signOut() {
    mAuth.signOut();
    updateUI(null);
}

private void sendEmailVerification() {
    // Disable button
    findViewById(R.id.verify_email_button).setEnabled(false);

    // Send verification email
    // [START send_email_verification]
    final FirebaseUser user = mAuth.getCurrentUser();
    user.sendEmailVerification()
            .addOnCompleteListener(this, new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                    // [START_EXCLUDE]
                    // Re-enable button
                    findViewById(R.id.verify_email_button).setEnabled(true);

                    if (task.isSuccessful()) {
                        Toast.makeText(EmailAuthActivity.this,
                                "Verification email sent to " + user.getEmail(),
                                Toast.LENGTH_SHORT).show();
                    } else {
                        Log.e(TAG, "sendEmailVerification", task.getException());
                        Toast.makeText(EmailAuthActivity.this,
                                "Failed to send verification email.",
                                Toast.LENGTH_SHORT).show();
                    }
                    // [END_EXCLUDE]
                }
            });
    // [END send_email_verification]
}

private boolean validateForm() {
    boolean valid = true;

    String email = mEmailField.getText().toString();
    if (TextUtils.isEmpty(email)) {
        mEmailField.setError("Required.");
        valid = false;
    } else {
        mEmailField.setError(null);
    }

    String password = mPasswordField.getText().toString();
    if (TextUtils.isEmpty(password)) {
        mPasswordField.setError("Required.");
        valid = false;
    } else {
        mPasswordField.setError(null);
    }

    return valid;
}

private void updateUI(FirebaseUser user) {
    hideProgressDialog();
    if (user != null) {
        mStatusTextView.setText(getString(R.string.emailpassword_status_fmt,
                user.getEmail(), user.isEmailVerified()));
        mDetailTextView.setText(getString(R.string.firebase_status_fmt, user.getUid()));

        findViewById(R.id.email_password_buttons).setVisibility(View.GONE);
        findViewById(R.id.email_password_fields).setVisibility(View.GONE);
        findViewById(R.id.signed_in_buttons).setVisibility(View.VISIBLE);

        findViewById(R.id.verify_email_button).setEnabled(!user.isEmailVerified());
    } else {
        mStatusTextView.setText(R.string.signed_out);
        mDetailTextView.setText(null);

        findViewById(R.id.email_password_buttons).setVisibility(View.VISIBLE);
        findViewById(R.id.email_password_fields).setVisibility(View.VISIBLE);
        findViewById(R.id.signed_in_buttons).setVisibility(View.GONE);
    }
}

@Override
public void onClick(View v) {
    int i = v.getId();
    if (i == R.id.email_create_account_button) {
        createAccount(mEmailField.getText().toString(), mPasswordField.getText().toString());
    } else if (i == R.id.email_sign_in_button) {
        signIn(mEmailField.getText().toString(), mPasswordField.getText().toString());
    } else if (i == R.id.sign_out_button) {
        signOut();
    } else if (i == R.id.verify_email_button) {
        sendEmailVerification();
    }
}

https://plnkr.co/edit/KNPThi?p=info

看看吧!

答案 4 :(得分:0)

找不到答案后,我自己在这里做了一些工作,并制作了一个Codepen,您可以使用它制作与您所描述的输入完全相同的进度条:圆的度数为100%,圆弧的半径和要填充的百分比。 Progress bar example (image)

HTML:

        let url = "https://.....someAudioFile.mp3"
        let source

        const getRecordingData = url => {
          let request = new XMLHttpRequest()

          request.open('GET', url, true)
          request.responseType = 'arraybuffer'
          request.send()

          request.onload = function() {
            let audioCtx = new (window.AudioContext || window.webkitAudioContext)()

            audioCtx.decodeAudioData(
              request.response,
              function onSuccess(decodedBuffer) {
                // Decoding was successful
                source = audioCtx.createBufferSource()
                source.buffer = decodedBuffer
                source.connect(audioCtx.destination)
                source.loop = false
                source.start(0)
              },
              function onFailure(e) {
                console.log('Error with decoding audio data' + e.err)
              }
            )
          }
        }

        getRecordingData(url)

CSS:

<section class="stat" id="sectionId">
  <svg viewbox="0 0 100 100">
    <path class="bar" d="
    M 10, 50
    a 40,40 0 1,0 80,0
    a 40,40 0 1,0 -80,0
   "/>
    <path class="progress" d="
      M 10, 50
    a 40,40 0 1,0 80,0
    a 40,40 0 1,0 -80,0
    "/>
  </svg>

  <script type="text/javascript">
    _.makeProgressBar("01", 240, 40, 86);
  </script>
</section>

JS:

.stat {
  width: 200px;
}

svg {
  display: block;
  transform-origin: center center;
  transform: rotate( 90deg );
}

path {
  stroke-linecap: round;
  stroke-width: 6px ;
  fill:none;
}