播放abcjs动画时没有移动光标

时间:2019-06-02 20:35:03

标签: angular abcjs

尝试使光标在图纸上移动。

Angular 7组件是:

  public createSheet(name: string) {
    // tslint:disable-next-line: max-line-length
    const tunes = 'T: Cooley\'s\n' +
    'M: 4/4\n' +
    'L: 1/8\n' +
    'R: reel\n' +
    'K: Emin\n' +
    '|:D2|EB{c}BA B2 EB|~B2 AB dBAG|FDAD BDAD|FDAD dAFD|\n' +
    'EBBA B2 EB|B2 AB defg|afe^c dBAF|DEFD E2:|\n' +
    '|:gf|eB B2 efge|eB B2 gedB|A2 FA DAFA|A2 FA defg|\n' +
    'eB B2 eBgB|eB B2 defg|afe^c dBAF|DEFD E2:|';

    const sheet = abcjs.renderAbc(name, tunes, { add_classes: true });
    setTimeout(() => {
      abcjs.startAnimation(name, sheet[0], { showCursor: true });
    }, 2000);
    return sheet;
  }

具有CSS内容:

.cursor-editor {
  width: 500px;
  margin-top: 12px;
}
.cursor-nav {
  margin-bottom: 12px;
}
.abcjs-cursor {
  background-color: rgba(196,196,196,.5);
}
.cursor {
    background-color: #ffffc0;
    opacity: 0.5;
    border-left: 1px solid black;
}

但这给了我错误:

core.js:15724 ERROR TypeError: paper.querySelector is not a function
    at Object.push.../../node_modules/abcjs/src/api/abc_animation.js.animation.startAnimation (abc_animation.js:38)
    at midi-lib.js:1457

源代码行为:

if (options.showCursor && !paper.querySelector('.abcjs-cursor')) {

查看源代码时,我可以看到参数paper应该是对象而不是字符串:

animation.startAnimation = function(paper, tune, options) {
  if (timer) {
    timer.stop();
    timer = undefined;
  }

  if (options.showCursor && !paper.querySelector('.abcjs-cursor')) {
    cursor = document.createElement('DIV');

但是除非我有错,否则动画example given会显示字符串的用法。

实际上,请看以下source code,我会看到以下内容:

console.error("ABCJS.startAnimation: When using scrollHorizontal/scrollVertical/scrollHint, the music must have been rendered using viewportHorizontal/viewportVertical.");else console.error("ABCJS.startAnimation: The second parameter must be a single tune. (Did you pass the entire array of tunes?)");else console.error("ABCJS.startAnimation: The first parameter must be a regular DOM element. (Did you pass a jQuery object or an ID?)");

但是上面给出的示例似乎与这些错误消息矛盾:

const tunes = abcjs.renderAbc("paper", abcString, { add_classes: true });

abcjs.startAnimation("paper", tunes[0], {
    showCursor: true,
});

第一个参数不是DOM元素,而是其id属性。

现在,我将尝试找出适合我的情况的参数。

更新:我可以毫无错误地接到startAnimation的电话,但是清除浏览器缓存后,仍然没有移动的光标。

setTimeout(() => {
  const element = document.getElementById(name);
  console.log(element);
  abcjs.startAnimation(element, sheet[0], { showCursor: true });
  console.log('Started the animation');
}, 2000);

或者,是否存在一种在渲染开始后将一个或几个乐曲添加到乐曲数组中的方法?为了使新的音符出现在工作表上,显示在一行中的木板上而不会中断,并且最古老的曲调消失,请使用类似abcjs.addTunes(element, sheet[0]);

的方法

更新:在这个示例页面中,我可以看到一个移动的动画光标,但是在我的Angular应用程序中仍然看不到。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="icon" href="favicon.ico" type="image/x-icon" />
    <script src="abcjs_midi_5.6.11-min.js" type="text/javascript"></script>
    <style media="screen" type="text/css">
    .abcjs-cursor {
      background-color: rgba(196,196,196,.5);
    }
    .cursor {
      background-color: #ffffc0;
      opacity: 0.5;
      border-left: 1px solid black;
    }
    </style>
  </head>
  <body>
    <div id="paper"></div>

    <script type="text/javascript">
var elementName = "paper";
var abcString = 'T: Cooley\'s\n' +
'M: 4/4\n' +
'L: 1/8\n' +
'R: reel\n' +
'K: Emin\n' +
'|:D2|EB{c}BA B2 EB|~B2 AB dBAG|FDAD BDAD|FDAD dAFD|\n' +
'EBBA B2 EB|B2 AB defg|afe^c dBAF|DEFD E2:|\n' +
'|:gf|eB B2 efge|eB B2 gedB|A2 FA DAFA|A2 FA defg|\n' +
'eB B2 eBgB|eB B2 defg|afe^c dBAF|DEFD E2:|';
console.log(elementName);
const tunes = ABCJS.renderAbc(elementName, abcString, { add_classes: true });
var element = document.getElementById(elementName);
console.log(element);
ABCJS.startAnimation(element, tunes[0], { showCursor: true, });
    </script>
  </body>
</html>

2 个答案:

答案 0 :(得分:0)

有一种使用TimingCallbacks方法进行动画处理的新方法,该方法更加灵活。 (在https://github.com/paulrosen/abcjs/blob/master/docs/api.md中搜索timingParams

var timer = new abcjs.TimingCallbacks(sheet[0], {
  beatCallback: this.beatCallbackIntercept,
  eventCallback: this.eventCallbackIntercept,
  lineEndCallback: this.lineEndCallbackIntercept,
});

timer.start();

然后,您负责在回调中进行所需的绘制。例如:

function initCursor() {
  var cursor = document.createElementNS(svgNS, "line");
  cursor.setAttribute("class", "abcjs-cursor");
  cursor.setAttributeNS(null, 'x1', 0);
  cursor.setAttributeNS(null, 'y1', 0);
  cursor.setAttributeNS(null, 'x2', 0);
  cursor.setAttributeNS(null, 'y2', 0);
  const svg = document.querySelector("#paper svg");
  svg.appendChild(cursor);
}

function setCursor(range) {
  if (range.measureStart && range.left === null)
    return; // this was the second part of a tie across a measure line. Just ignore it.
  let cursor = document.querySelector(".abcjs-cursor");
  cursor.setAttribute("x1", range.left-2);
  cursor.setAttribute("x2", range.left-2);
  cursor.setAttribute("y1", range.top);
  cursor.setAttribute("y2", range.top + range.height);
}

对于您的第二个问题:事后没有办法添加音乐,您必须重画,但是我发现重画非常快。如果要添加整个乐曲,我将创建更多的div来放置音乐,而不是重新绘制所有乐曲。

以上动画方法可以随时调出音调,因此光标将平滑移动:

timer.replaceTarget(sheet[0])

答案 1 :(得分:0)

我设法绘制了光标,但我认为这不是官方的解决方法。

abcjs方法中初始化ngOnInit之后:

this.testSheet = abcjs.renderAbc('test', this.notes, {scrollHorizontal: true});

我设法像这样为test元素添加了自定义光标:

const sheet = document.getElementById('test');
const cursor = document.createElement('div');
cursor.className = 'abcjs-cursor';
sheet.style.position = 'relative';
cursor.style.background = 'red';
cursor.style.position = 'absolute';
sheet.appendChild(cursor);

如您所见,您可以根据需要设置cursor的格式。 我必须像这样添加游标,因为abcjs检查cursor是否在DOM中。如果没有,它将添加自己的光标

abc_animation.js 第38行:

if (options.showCursor) {
        cursor = paper.querySelector('.abcjs-cursor');
        if (!cursor) {
            cursor = document.createElement('DIV');
            cursor.className = 'abcjs-cursor cursor';
            cursor.style.position = 'absolute';

            paper.appendChild(cursor);
            paper.style.position = 'relative';
        }
    }

这是 Component.html 文件:

<button (click)="start()">Play</button>
<div id="test"></div>

这是start()方法:

start() {
  const element = document.getElementById('test');
  abcjs.startAnimation(element, this.testSheet[0], {showCursor: true});
}

我认为这不是Angular中的最佳实践,但是,嘿!有用! (对我来说)