美文网首页
js动画特效之打字机效果: easy-typer-js

js动画特效之打字机效果: easy-typer-js

作者: MC桥默 | 来源:发表于2020-01-03 10:57 被阅读0次
让文字像打字机一样一个个的显示在页面上,应该会给用户一种比较炫酷的感觉
easy-typer.gif

直接上代码

<!-- html代码 -->
<script src="./index.js"></script>
<style>
  .easy-typed-cursor {
    margin-left: 10px;
    opacity: 1;
    -webkit-animation: blink 0.7s infinite;
    -moz-animation: blink 0.7s infinite;
    animation: blink 0.7s infinite;
  }
  .output-wrapper {
    margin-top: 30vh;
    text-align: center;
    font-size: 20px;
  }
  .img {
    width: 300px;
  }
  .img-2 {
    width: 100px;
  }
  @keyframes blink {
    0% {
      opacity: 1;
    }
    50% {
      opacity: 0;
    }
    100% {
      opacity: 1;
    }
  }
  @-webkit-keyframes blink {
    0% {
      opacity: 1;
    }
      
    50% {
      opacity: 0;
    }
    100% {
      opacity: 1;
    }
  }
  @-moz-keyframes blink {
    0% {
      opacity: 1;
    }
    50% {
      opacity: 0;
    }
    100% {
      opacity: 1;
    }
  }
  
    
</style>
<div class="output-wrapper"><span id="output"></span><span class="easy-typed-cursor">|</span></div>
<script>
  const obj = {
    output: '', // 输出内容  使用MVVM框架时可以直接使用
    type: 'rollback',
    isEnd: false,
    speed: 80,
    backSpeed: 80,
    sleep: 3000,
    singleBack: true,
    sentencePause: true
  }
  const textList = [`黎明前的黑暗是最深不见底的黑暗!`, `世界上本没有无用的齿轮,只有齿轮自身能决定它的用途!`, `天不生我彭小呆,万古长青一生狂!`]
  const typing = new EasyTyper(obj, textList, ()=>{
    // 此回调结束了easyTyper的生命周期
    console.log('结束了,我的使命!')
  }, (output, instance) => {
    // 钩子函数,每一帧的数据获取和实例EasyTyper的获取
    console.log(output)
    document.getElementById('output').innerHTML = `${output}`
  })
</script>
/*js代码*/
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  return new (P || (P = Promise))(function (resolve, reject) {
      function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
      function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
      function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
      step((generator = generator.apply(thisArg, _arguments || [])).next());
  });
};
class EasyTyper {
  constructor(obj, input, fn, hooks) {
      checkKeyIsNull(obj);
      checkFieldIsError(obj);
      this.obj = obj;
      this.input = typeof input === 'string' ? [input] : input;
      this.fn = typeof fn === 'function' ? fn : function () { };
      this.hooks = typeof hooks === 'function' ? hooks : function () { };
      this.timer = 0;
      this.typeAction = {
          rollback: this.typedBack.bind(this),
          normal: this.play.bind(this),
          custom: this.fn
      };
      // 实例化完后立即执行打字输出
      this.init();
  }
  init() {
      this.play();
  }
  // 打字
  play() {
      if (!this.input.length)
          return this.fn(this);
      let i = 0, stop = false, input = this.input.shift() || '';
      this.timer = setInterval(() => {
          if (i === input.length) {
              i = 0;
              stop = true;
              this.closeTimer();
          }
          if (this.obj.isEnd)
              return this.closeTimer();
          if (stop)
              return this.nextTick();
          this.obj.output = input.slice(0, i + 1);
          this.hooks(input.slice(0, i + 1), this);
          i++;
      }, this.obj.speed);
  }
  // 回滚方法
  typedBack() {
      // 如果句子出书完毕,且是句子暂停模式
      if (!this.input.length && this.obj.sentencePause)
          return this.fn(this);
      let input = this.obj.output;
      let i = input.length, stop = false;
      this.timer = setInterval(() => {
          if (i === -1) {
              this.obj.output = '';
              this.hooks('', this);
              i = 0;
              stop = true;
              this.closeTimer();
          }
          if (this.obj.isEnd) {
              this.closeTimer();
              return this.obj.singleBack = false;
          }
          if (stop) {
              this.obj.singleBack = false;
              return (() => {
                  const { length } = this.input;
                  return length ? this.play() : this.fn(this);
              })();
          }
          this.obj.output = input.slice(0, i + 1);
          this.hooks(input.slice(0, i + 1), this);
          i--;
      }, this.obj.backSpeed);
  }
  // 下一次触发方式
  nextTick() {
      return __awaiter(this, void 0, void 0, function* () {
          // 等待
          yield this.sleep(this.obj.sleep);
          return this.obj.singleBack ? this.typedBack() : this.getOutputType();
      });
  }
  // 输出方式
  getOutputType() {
      return this.typeAction[this.obj.type](this);
  }
  // 关闭定时器
  closeTimer() {
      clearInterval(this.timer);
  }
  // 线程等待
  sleep(ms) {
      return new Promise(resolve => setTimeout(resolve, ms));
  }
  // 结束
  close() {
      return this.obj.isEnd = true;
  }
}
// 错误提示语
const errorTip = (message) => {
  throw new Error(message);
};
// 校验参数完整性
const checkKeyIsNull = (obj) => {
  const props = {
      output: '',
      type: '',
      isEnd: false,
      speed: 80,
      backSpeed: 40,
      sleep: 3000,
      singleBack: false,
      sentencePause: false
  };
  const propsKeys = Object.keys(props);
  const objKeys = Object.keys(obj);
  if (propsKeys.length !== objKeys.length) {
      errorTip('配置对象错误: 字段数量不正确!');
  }
  propsKeys.forEach(key => {
      if (obj[key] === undefined || obj[key] === null) {
          errorTip('配置对象错误:字段值为null或undefined!');
      }
  });
};
// 检验参数类型
const checkFieldIsError = (obj) => {
  Object.keys(obj).forEach(key => {
      const proxy = EasyTyperStrategy[key](obj);
      if (proxy.check()) {
          proxy.showTip(key);
      }
  });
};
// 策略分发
const EasyTyperStrategy = (() => ({
  output: (obj) => {
      return new CheckField(`string`, obj.output);
  },
  type: (obj) => {
      return new CheckField(`string`, obj.type);
  },
  isEnd: (obj) => {
      return new CheckField(`boolean`, obj.isEnd);
  },
  speed: (obj) => {
      return new CheckField(`number`, obj.speed);
  },
  backSpeed: (obj) => {
      return new CheckField(`number`, obj.backSpeed);
  },
  sleep: (obj) => {
      return new CheckField(`number`, obj.sleep);
  },
  singleBack: (obj) => {
      return new CheckField(`boolean`, obj.singleBack);
  },
  sentencePause: (obj) => {
      return new CheckField(`boolean`, obj.sentencePause);
  },
}))();
// 字段校验类
class CheckField {
  constructor(type, field) {
      this.type = type;
      this.field = field;
  }
  check() {
      return typeof this.field !== `${this.type}`;
  }
  showTip(name) {
      errorTip(`配置对象错误:属性 ${name} 必须为 ${this.type} 类型!`);
  }
}

相关文章

  • js动画特效之打字机效果: easy-typer-js

    让文字像打字机一样一个个的显示在页面上,应该会给用户一种比较炫酷的感觉 直接上代码

  • [JS插件]功能十分强大的打字机效果: easy-typer-j

    easy-typer-js 功能十分强大打字机插件,兼容原生JS和MVVM类框架(Vue, React...),随...

  • 文字特效

    18种基于anime.js的文字动画特效效果演示CSS3文字烟雾散开动画特效canvas+原生js实现立体式文字变...

  • 网站推荐 (不定时更新)

    1.网页设计 jQuery插件库:JS特效,网页特效,以及各种html5,css3动画和效果Bootstrap,来...

  • 2.14号

    总结:单词完成 js特效复习 开始看js动画 网课看了8节 计划: 单词 js动画和特效 网课 对这段时间所学进行总结

  • anime.js实现logo动画

    之前无聊浏览特效的时候,发现了anime.js的logo动画特效,于是也想整个自己的logo动画。着手coding...

  • 16 - 序列图片

    HTML结构 Css样式 Js代码 特效展示 此动画并不完整 会有点bug 但是足够可以帮助小白理解Js动画

  • 浅谈jQuery之动画

    背景 jQuery提供了JS未能提供的动画效果,利用jQuery的动画效果,可以极大的简化JS动画部分的逻辑 滑入...

  • [JS插件]酷炫的打字机效果: Typed.js

    一. Type.js效果演示 Type.js是一个轻量级的插件, 用于实现页面文字的打字机效果. 它使用起来非常简...

  • Vue中的Js动画与Velocityjs的结合

    通过Vue中的js动画生命周期函数实现动画效果 js常用动画库 velocity.js velocity.js 官...

网友评论

      本文标题:js动画特效之打字机效果: easy-typer-js

      本文链接:https://www.haomeiwen.com/subject/ggczoctx.html