将数据转换为屏幕坐标

时间:2015-04-24 10:24:43

标签: javascript canvas

我想使用函数将数据转换为javascript中的屏幕坐标。该函数必须如下所示:

function createTransform(domain, range){
    // domain is a two-element array of the domain’s bounds
    // range is a two-element array of the range’s bounds
    // implement the actual calculation here
    var alpha = ...;
    var beta = ...;
    return function(x){
        return alpha * x + beta;
    };
}

// to use this for instance:
var tranform = createTransform([10, 20], [10, 20]);
console.log(transform(15));  // should log 15

我已经看了几个小时,但仍然不理解。

2 个答案:

答案 0 :(得分:1)

这是如何获取数据值并将其缩放以适应屏幕。它使用映射函数在给定特定数据值的情况下计算所需的屏幕值。

function mapRange(value, dataLow, dataHigh, screenLow, screenHigh) {
    return screenLow +
         (value - dataLow) * (screenHigh - screenLow) / (dataHigh - dataLow);
}

工作原理

从本质上讲,您必须缩放输入数据范围,以适应专用于显示数据的任何屏幕坐标范围。

您正在将一个范围扩展为另一个范围。您可能会将比例因子视为数据范围与屏幕范围的百分比。

// calculate the scaling factor required to fit the data inside the screen
var scalingFactor = screenRange / dataRange;

所有数据点都在数据范围内,计算方式如下:

// calculate the min/max range of all data
var dataRange= maximumDataValue – minimumDataValue;

所有屏幕坐标都在屏幕范围内,计算方式如下:

// calculate the min/max range of all screen coordinates
//     that are dedicated to displaying the data
var screenRange = maximumScreenCoordinateValue – minimumScreenCoordinateValue;

如果您想使用全屏,则screenRange将成为屏幕宽度。

下一步是计算整个数据范围内特定数据点的相对位置:

// calculate any one specified data-point's relative position within
// the full data range
var thisDatumPositionInDataRange = thisDataValue – minimumDataValue;

最后,使用scalingFactor将特定数据值映射(==缩放)到可用的屏幕坐标上。

// calculate the screen coordinate where the specified dataum
//    will be displayed
var screenCoordinate = minimumScreenValue + thisDatumPositionInDataRange * scalingFactor;

用语言来说,这个计算意味着:

•从最小(==最左侧)屏幕坐标开始。

•按照scalingFactor缩放的指定基准面的相对位置(在其数据范围内)向右移动屏幕。

以下是带注释的代码示例:

// supply a data value (value)
// and supply the min & max of the datum and the screen size
// return value mapped to fit onto the screen
function mapRange(value, dataLow, dataHigh, screenLow, screenHigh) {
    return screenLow + (screenHigh - screenLow) * (value - dataLow) / (dataHigh - dataLow);
}

// calculate the max & min of a given array
function calcDataMinMax(a){
    var min=1000000;
    var max=-1000000;
    for(var i=0;i<a.length;i++){
        var value=a[i];
        if(value<min){min=value;}
        if(value>max){max=value;}
    }
    return({min:min,max:max});
}

// Usage:

// example data
var data=[5,10,-3,20,0,2];

// example screen width
var screenWidthMin=0;
var screenWidthMax=640;

// calc the min and max of values in your data
var dataRange=calcDataMinMax(data);

// map the data value 8 to fit onto the screenWidth
var map8=mapRange(8,dataRange.min,dataRange.max,0,100);

答案 1 :(得分:0)

function createTransform(domain, range) {

  var domain_min = domain[0];
  var domain_max = domain[1];
  var range_min = range[0];
  var range_max = range[1];

  var beta = (range_max / domain_max - range_min / domain_min) * (domain_min * domain_max) / (domain_min - domain_max);

  var alpha = (range_min - beta) / domain_min;

  return function(x) {
    return alpha * x + beta;
  };
}

function createTransform(domain, range) {

  var domain_min = domain[0];
  var domain_max = domain[1];
  var range_min = range[0];
  var range_max = range[1];

  var beta = (range_max / domain_max - range_min / domain_min) * (domain_min * domain_max) / (domain_min - domain_max);

  var alpha = (range_min - beta) / domain_min;

  return function(x) {
    return alpha * x + beta;
  };
}

var calculateButton = document.querySelector('.calculate');
var domain_minInput = document.querySelector('.domain_min');
var domain_maxInput = document.querySelector('.domain_max');
var range_minInput = document.querySelector('.range_min');
var range_maxInput = document.querySelector('.range_max');
var xInput = document.querySelector('.x');
var resultBox = document.querySelector('.result');


calculateButton.addEventListener('click', function() {
  var domain_min = parseInt(domain_minInput.value);
  var domain_max = parseInt(domain_maxInput.value);
  var range_min = parseInt(range_minInput.value);
  var range_max = parseInt(range_maxInput.value);
  var x = parseInt(xInput.value);
  var transform = createTransform([domain_min, domain_max], [range_min, range_max]);
  resultBox.textContent = transform(x);
});
input {
  display: block;
}
domain_min
<input class="domain_min">domain_max
<input class="domain_max">range_min
<input class="range_min">range_max
<input class="range_max">x
<input class="x">
<button class="calculate">Calculate</button>
<h3>result:</h3>
<div class="result"></div>