0

価格を設定するためのGUIをまとめようとしています。
グラフィカルに表示される3つのカテゴリと、推奨される売買価格を設定するために使用する2つのスライダーがあります。

演習として、いくつかのプロトタイプをまとめて、ここjsFiddleに配置しました。
ざっと見てください、それは私の言葉よりもはるかに効果的にそれを説明します: )
(私のJSを許してください...まだそれをリファクタリングしていません)

私たちの目標は、スライダーをHTML入力でフロートに設定することなので、私はSVGに傾倒しています。

  1. 私の最初の要求は、SVGソリューションを説得するための私の選択のピアレビューです...私が遭遇しなければならない固有の痛みを伴う問題がないことを確認したいだけです。私は他の解決策についても議論を受け入れています。
  2. 2番目は質問です。図形の位置に基づいて入力値を設定する方法を理解するのに役立つ、投稿するのに適したリンク/例はありますか?

(位置は定義された$$範囲のパーセンテージを表すと予想しているため、特定の$$値を推定できます)

ありとあらゆる助けを大いに感謝します。

4

1 に答える 1

0

これが私が作成したデモで、SVGを使用して4つの入力を設定し、その逆も同様です。http:
//phrogz.net/svg/complex-plane-picker.xhtml

上位2つの入力は、XとY(実際のコンポーネントと複雑なコンポーネント)です。下の2つは極座標(大きさと角度)です。

必要以上のコードが含まれている可能性があります(エッジ/中央に近づくと自動スケーリングされ、更新された軸ティックが描画されます)。これにより、デモとして役立つよりも混乱する可能性があります。

ただし、一般的には、次のことを行う必要があります。

  • keyup入力のorまたはchangeorイベントにイベントリスナーを設定し、それinputに応じてSVGを更新して一致させます。
  • SVG要素にドラッグを追加し、ドラッグ中に適切な値を計算し、.valueそれに応じて入力のを設定します。

mousemoveヒントとして、ドラッグ中は、ドラッグ可能な要素自体を検出しようとしないでください。マウスがこれの外側に移動すると、ドラッグイベントの取得が停止し、追いつくことができなくなります。代わりに、私は通常、このロジックを使用します。

  • オンmousedown
    1. 現在のカーソル位置を記録します
    2. ドキュメントのルートにmousemoveハンドラーを登録します
    3. ドキュメントのルートにmouseupハンドラーを登録します
  • オンmousemove
    1. 現在のカーソル位置とドラッグ開始時の位置の間の画面スペースのデルタを検出し、これを使用して、ドラッグされている要素のローカルスペースのデルタを計算し、その変換を更新します。
  • オンmouseup
    1. mousemoveハンドラーの登録を解除します。

万が一サイトがダウンした場合の完全なソースコードは次のとおりです。

<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><head> 
  <meta http-equiv="content-type" content="application/xhtml+xml; charset=utf-8" />
  <title>SVG Complex Plane Input</title>
  <style type="text/css" media="screen">
    html, body { background:#eee; margin:0 }
    p { margin:0.5em; text-align:center }
    .complex-plane-picker svg { width:200px; height:200px; display:block; margin:1em auto; stroke-linejoin:round; stroke-linecap:round; pointer-events:all; }
    .complex-plane-picker rect.bg { fill:#fff; }
    .complex-plane-picker .axes * { stroke:#ccc; fill:none }
    .complex-plane-picker .dot { fill:#090; fill-opacity:0.4; stroke:#000; stroke-opacity:0.6; cursor:move; }
    .complex-plane-picker input { width:6em; }
    .complex-plane-picker .labels { stroke:none; font-size:6px; font-family:'Verdana'; text-anchor:middle; alignment-baseline:middle; }
    .complex-plane-picker .scalers { pointer-events:all; }
  </style>
</head><body>
<p>Drag the dot to set the complex value.<br/> TODO: Hold down shift to affect only the magnitude. Hold down alt to affect only the angle. Hold down both to snap to the nearest real- or imaginary-only value.</p>
<div class="complex-plane-picker">
  <p class="rectangular"><input type="number" value="0" class='real' />+<input type="number" value="0" class='imaginary' />i</p>
  <svg viewBox="-50 -50 100 100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" baseProfile="full">
    <rect class="bg" x="-50" y="-50" width="100" height="100" />
    <g class="scalers">
      <rect x="-5" y="-5" width="10" height="10" fill="#ffc"/>
      <rect x="-45" y="-45" width="90" height="90" fill="none" stroke="#ffc" stroke-width="10" />
    </g>
    <g class="axes">
      <g>
        <line x1="-49" y1="0" x2="49" y2="0" />
        <polyline points="-44,5 -49,0 -44,-5" />
        <polyline points="44,5 49,0 44,-5" />
      </g>
      <g transform="rotate(90)">
        <line x1="-49" y1="0" x2="49" y2="0" />
        <polyline points="-44,5 -49,0 -44,-5" />
        <polyline points="44,5 49,0 44,-5" />
      </g>
    </g>
    <g class="labels" id="labels">
      <text x="0" y="0">0</text>
      <text x="0" y="0">0</text>
      <text x="0" y="0">0</text>
      <text x="0" y="0">0</text>
    </g>
    <use class="labels" xlink:href="#labels" transform="rotate(90)" />
    <circle class="dot" r="4" />
  </svg>
  <p class="polar"><input type="number" value="0" class='magnitude' />@<input type="number" value="0" class='angle'/>°</p>
</div>
<script type="text/javascript"><![CDATA[
  var svg   = document.getElementsByTagName('svg')[0];
  var svgNS = svg.getAttribute('xmlns');
  var pt    = svg.createSVGPoint();

  function mxy(evt){
    pt.x = evt.clientX;
    pt.y = evt.clientY;
    return pt.matrixTransform(svg.getScreenCTM().inverse());
  }

  var dot  = document.querySelector('.complex-plane-picker .dot');
  var real = document.querySelector('.real');
  var imag = document.querySelector('.imaginary');
  var size = document.querySelector('.magnitude');
  var angl = document.querySelector('.angle');

  var labels = svg.querySelectorAll('.complex-plane-picker #labels text');
  var scale, maxValue;
  var updateScale = function(newScale){
    scale = newScale;
    maxValue = 50*scale;
    var tickSize=1e-6;
    var e=-5;
    var f=-1;
    var fs = [1,2,5]
    while (tickSize/scale < 10){
      if (++f%fs.length==0) ++e;
      tickSize = fs[f%fs.length]*Math.pow(10,e);
    }
    for (var i=labels.length;i;--i){
      labels[i-1].firstChild.nodeValue = (tickSize*i).toString().replace(/(\.0*[^0]+)0{3,}.*/,'$1');
      labels[i-1].setAttribute('y', -tickSize*i/scale);
    }
    // updateRectangularFromDot();
    // updatePolarFromDot();
  };

  var rescaleAsNeeded = function(x,y,jump){
    var scaleFactor = 1.03;
    if (jump && (x>maxValue || y>maxValue || (x<maxValue*0.1 && y<maxValue*0.1))){
      updateScale(Math.max(x,y)*2/50);
    } else if (x>maxValue*0.8 || y>maxValue*0.8) updateScale(scale*scaleFactor);
    else if (x<maxValue*0.1 && y<maxValue*0.1) updateScale(scale/scaleFactor);
  };  

  var updateFromRectangular = function(){
    var x = real.value*1;
    var y = imag.value*1;
    rescaleAsNeeded(x,y,true);
    dot.cx.baseVal.value =  x/scale;
    dot.cy.baseVal.value = -y/scale;
    updatePolarFromDot();
  };
  real.addEventListener('input',updateFromRectangular,false);
  imag.addEventListener('input',updateFromRectangular,false);

  var updateFromPolar = function(){
    var hyp = size.value*1;
    var rad = angl.value*Math.PI/180;
    var x   = Math.cos(rad)*hyp;
    var y   = Math.sin(rad)*hyp;
    rescaleAsNeeded(x,y,true);
    dot.cx.baseVal.value =  x/scale;
    dot.cy.baseVal.value = -y/scale;
    updateRectangularFromDot();
  };
  size.addEventListener('input',updateFromPolar,false);
  angl.addEventListener('input',updateFromPolar,false);

  var updateRectangularFromDot = function(){
    real.value = ( dot.cx.baseVal.value*scale).toFixed(2);
    imag.value = (-dot.cy.baseVal.value*scale).toFixed(2);
  };
  var updatePolarFromDot = function(){
    var x =  dot.cx.baseVal.value*scale;
    var y = -dot.cy.baseVal.value*scale;
    size.value = Math.sqrt(x*x+y*y).toFixed(2);
    angl.value = (Math.atan2(y,x)*180/Math.PI).toFixed(1);
  }
  var dragging = false;
  dot.addEventListener('mousedown',function(evt){
    var offset = mxy(evt);
    dragging = true;
    offset.x = dot.cx.baseVal.value - offset.x;
    offset.y = dot.cy.baseVal.value - offset.y;
    var scaleTimer;
    var move = function(evt){
      clearTimeout(scaleTimer);
      var now = mxy(evt);
      var x = offset.x + now.x;
      var y = -(offset.y + now.y);
      dot.cx.baseVal.value = x;
      dot.cy.baseVal.value = -y;
      x = Math.abs(x)*scale, y=Math.abs(y)*scale;
      var oldScale = scale;
      rescaleAsNeeded(x,y);
      updatePolarFromDot();
      updateRectangularFromDot();
      if (oldScale != scale) scaleTimer = setTimeout(function(){move(evt)},1000/30);
    };
    document.documentElement.style.userSelect = 
    document.documentElement.style.MozUserSelect = 
    document.documentElement.style.webkitUserSelect = 'none';
    svg.addEventListener('mousemove',move,false);
    document.documentElement.addEventListener('mouseup',function(){
      dragging = false;
      clearTimeout(scaleTimer);
      svg.removeEventListener('mousemove',move,false);
      document.documentElement.style.userSelect = 
      document.documentElement.style.MozUserSelect = 
      document.documentElement.style.webkitUserSelect = '';
    },false);
  },false);

  dot.addEventListener('dblclick',function(){
    dot.cx.baseVal.value = dot.cy.baseVal.value = 0;
    updateScale(1.0);
    updatePolarFromDot();
    updateRectangularFromDot();
  },false);

  updateScale(1.0);

]]></script>
</body></html>
于 2012-06-20T22:19:59.753 に答える