ラテックススタイルの方程式を含むAngularJS双方向バインディングテキストを使用しようとしています。方程式をフォーマットするためにMathJaxを呼び出したいのですが、AngularJSがモデルの変更を完了した後にMathJaxが呼び出されるようにするための最良の方法がわかりません。コールバックが必要だと思います。これが私のJavaScriptです:
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.Update = function() {
$scope.Expression = 'Evaluate: \\( \\frac{9}{4} \\div \\frac{1}{6} \\)';
MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
}
$scope.Expression = 'Evaluate: \\( \\frac{5}{4} \\div \\frac{1}{6} \\)';
}
そして、これが私のHTMLです。
<div ng-controller="MyCtrl">
<button ng-click="Update()">Update</button>
{{Expression}}
</div>
フィドルはここにあります: http://jsfiddle.net/LukasHalim/UVjTD/1/ 。フィドルでは、更新ボタンを2回クリックしても元の式が削除されないことに気付くでしょう。これは、バグまたは競合のようです。
MathJaxとの戦いで何日も(そしておそらく何週間も)無駄になってきた私は、その場で数式を更新するというさまざまな癖に精通しています。私はAngularに慣れていないのですが、これは私に飛び込む良い機会を与えてくれました、そして私は私の問題を解決する解決策に行き着きました-うまくいけばそれはあなたの問題も解決するでしょう。
ライブデモ: jsfiddle
Angularが提供する単純な補間を使用する代わりに、 _ng-bind
_ に基づいて_mathjax-bind
_と呼ばれる新しいディレクティブを作成しました。
expression
が数学コードを含む変数である場合、\( {{expression}} \)
の代わりに次のように記述できます。
_<span mathjax-bind="expression"></span>
_
そして、すべてが適切な時期に植字され、更新されます。
ディレクティブのサポートコードは次のとおりです。
_myApp.directive("mathjaxBind", function() {
return {
restrict: "A",
controller: ["$scope", "$element", "$attrs",
function($scope, $element, $attrs) {
$scope.$watch($attrs.mathjaxBind, function(texExpression) {
var texScript = angular.element("<script type='math/tex'>")
.html(texExpression ? texExpression : "");
$element.html("");
$element.append(texScript);
MathJax.Hub.Queue(["Reprocess", MathJax.Hub, $element[0]]);
});
}]
};
});
_
最も単純で、最も速く、最も安定したソリューション:
$rootScope.$watch(function(){
MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
return true;
});
利点:
mathjax-bind
ディレクティブがある場合(別の回答が示唆しているように)、レンダリングが遅くなります。この点が私が別の答えを探していた理由です。ベンチマーク:100 mathjax-bind
ディレクティブは63秒かかりましたが、このメソッドではページのレンダリングに1.5秒かかりました。この関数はダイジェストサイクルごとに呼び出されるため、頻繁に実行されることはわかっていますが、ページの速度が著しく低下することはありません。
ベン・アルパートの答えを拡張した簡単なフィドルを作成しました。これが フィドル と プランク です。
具体的には、テキストにMathjaxによって変換されるテキストの一部しかない場合は、これを使用できます。インラインmathjaxの場合は、テキストを$で囲む必要があり、ブロック表示の場合は、ブロックを$$で囲む必要があります。 (対応する正規表現を作成する場合は、任意の形式を使用できます)
app.js
MathJax.Hub.Config({
skipStartupTypeset: true,
messageStyle: "none",
"HTML-CSS": {
showMathMenu: false
}
});
MathJax.Hub.Configured();
var myApp = angular.module("myApp", []);
myApp.directive("mathjaxBind", function() {
return {
restrict: "A",
scope:{
text: "@mathjaxBind"
},
controller: ["$scope", "$element", "$attrs", function($scope, $element, $attrs) {
$scope.$watch('text', function(value) {
var $script = angular.element("<script type='math/tex'>")
.html(value == undefined ? "" : value);
$element.html("");
$element.append($script);
MathJax.Hub.Queue(["Reprocess", MathJax.Hub, $element[0]]);
});
}]
};
});
myApp.directive('dynamic', function ($compile) {
return {
restrict: 'A',
replace: true,
link: function (scope, ele, attrs) {
scope.$watch(attrs.dynamic, function(html) {
html = html.replace(/\$\$([^$]+)\$\$/g, "<span class=\"blue\" mathjax-bind=\"$1\"></span>");
html = html.replace(/\$([^$]+)\$/g, "<span class=\"red\" mathjax-bind=\"$1\"></span>");
ele.html(html);
$compile(ele.contents())(scope);
});
}
};
});
function MyCtrl($scope, $element) {
$scope.html = "A coin of is $ \\frac{5}{4} $ thrown $$\\frac{1}{6}$$ dfv";
}
index.html
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<script src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML&delayStartupUntil=configured&dummy=.js"></script>
<link rel="stylesheet" href="style.css" />
<script data-require="[email protected]" src="http://code.angularjs.org/1.2.7/angular.js" data-semver="1.2.7"></script>
<script src="app.js"></script>
</head>
<body>
<div ng-controller="MyCtrl">
<input type="text" ng-model="html"/><br/>
<div dynamic="html"></div>
</div>
</body>
style.css
input[type="text"] {
width: 800px;
}
.red{
color:red;
display:inline-block;
}
.blue{
color:blue;
display:block;
}
これは、式内でダブルカーリーマークアップを使用できるようにするディレクティブです(スコープに式変数を設定する必要はありません)。これは このブログ投稿 に基づいていますが、MathJaxのみをサポートし、コンパイルされたDOMを保存して、スコープ変数の変更時に更新されるようにします。
アレックスオズボーンが言ったように、非数学を数学から分離するのが最善です。
使用法:
<p>This is inline math: <latex>x^{ {{power}} }</latex>,
and this is display math: <div latex> y^{ {{power}} } .</div></p>
スニペット:
angular.module('app', [])
.controller('ctrl', function($scope) {
$scope.power = "\\sin(x^2)";
})
.directive('latex', function() {
return {
restrict: 'AE',
link: function(scope, element) {
var newDom = element.clone();
element.replaceWith(newDom);
var pre = "\\(",
post = "\\)";
if (element[0].tagName === 'DIV') {
pre = "\\[";
post = "\\]";
}
scope.$watch(function() {
return element.html();
}, function() {
console.log(element);
newDom.html(pre + element.html() + post);
MathJax.Hub.Typeset(newDom[0]);
});
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<div ng-app="app" ng-controller="ctrl">
<p>Power:
<input ng-model="power" />
</p>
<p>This is the inline latex,
<latex>x^{ {{power}} }</latex>, followed by some display mode latex
<div latex>y^{ {{power}} } = {{power}}.</div>And that's it!
</p>
</div>
簡単な解決策は、$ timeoutを使用してMathJax.Hub.Queue(["Typeset", MathJax.Hub])
をブラウザーのイベントキューに入れることです( DOMのレンダリングが終了した後にディレクティブを実行する を参照)。
このようなもの:
var app = angular.module('myApp', []);
app.controller('myController', function ($scope, $timeout) {
controller = this;
$scope.Update = function () {
$scope.value = " \\( \\frac{5}{4} \\div \\frac{1}{6} \\)";
$timeout(controller.updateMathJax, 0);
}
this.updateMathJax = function () {
MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
}
});
私の変更を試すことができます http://jsfiddle.net/bmma8/4/ 入力を変更するか、ボタンをクリックすると式が更新されます。
js:
MathJax.Hub.Config({
extensions: ["tex2jax.js"],
jax: ["input/TeX","output/HTML-CSS"],
tex2jax: {inlineMath: [["$","$"],["\\(","\\)"]]}
});
var myApp = angular.module('myApp',[]);
function MyCtrl($scope, $log) {
var QUEUE = MathJax.Hub.queue; // shorthand for the queue
$scope.Update = function() {
QUEUE.Push(["Text",MathJax.Hub.getAllJax("MathOutput")[0],"\\displaystyle{"+ $scope.Expression+"}"]);
//$scope.Expression = 'Updated Expression: \\( \\frac{9}{4} \\div \\frac{1}{6} \\)';
//MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
}
$scope.Expression = 'Original Expression: \\( \\frac{5}{4} \\div \\fra
およびhtml:
<div ng-controller="MyCtrl">
<button ng-click="Update()">Update</button>
<input ng-model="Expression" ng-change="Update()">
<div id="MathOutput">
You typed: ${}$
</div>
</div>
アレクサンドル
見てください http://jsfiddle.net/pz5Jc/
テンプレート内:
{{Label}} <span id="mathElement">{{Expression}}</span>
コントローラー内:
$scope.Update = function() {
$scope.Expression = '\\frac{9}{4} \\div \\frac{1}{6}';
$scope.Label = 'Updated Expression:'
var math = MathJax.Hub.getAllJax("mathElement")[0];
math.Text('\\frac{4}{4} \\div \\frac{2}{6}');
}
ポイントのカップル:
私はmathjaxにあまり精通していませんが、次のようになります。
私は実際に別の解決策を考えました。いくつかのangularと数学をレンダリングすると、次のようになります。
角度コントローラー
$scope x = 5;
HTML
<h3> {{ '$ Multiplication = '+ x + ' * 2 =' + (x*2) + '$'}} </h3>
フォーマットされたMathJaxの結果
乗算= 5 * 2 = 1
重要なのは、括弧内にドル記号をテキストとして含めることです。 Angularがそれらをレンダリングすると、ドル記号はプレーンテキストとして表示されますが、Math Jax形式が実行されると、ドル記号を認識して魔法を実行します。
このためのディレクティブを作成します。
フィドル: http://jsfiddle.net/8YkUS/1/
HTML
p data-math-exp data-value = "math">
JAVASCRIPT
appFlipped.directive("mathExp", function () {
return {
scope: {
value: "="
},
link: function (scope, el) {
var domEl = el[0];
scope.$watch("value", function (newValue) {
//nothing to do here
if (newValue == null || window.MathJax == null)return;
//update the dom with the new value and pass the hub for styling the equation
domEl.innerHTML = '`' + newValue + '`';
MathJax.Hub.Queue(["Typeset", MathJax.Hub, domEl]);
});
}
}
});
私はロニーの解決策をもう少しいじった。表示計算は表示モードで表示する必要があります。と
<script type="math/tex; mode=display">
生成されたスパンに属性を追加して、それを示しました。
フィドルはここにあります http://jsfiddle.net/repa/aheujhfq/8/