Языки программирования – 7
Отсутствие красивого, т.е подходящего во всех ситуациях общего решения для работы в Интернете никак не мешает просачиваться через ситуацию с перегонкой данных так как это подходит для конкретной задачи.
Браузер не только страницу рисовать по переданному тексту HTML умеет. Это полноценный интерпретатор программных текстов. Если ему передать программу, описывающую что делать по нажатию кнопки без обращения к серверу он прекрасно её выполнит.
Можно, например, передать пользователю все итоговые цифры (договора, выпуск, продажи, и т.д) и дать возможность менять вид экрана (конкретные таблицы, графики) без обращения к серверу. Это всё будет делать интерпретатор языка – СКРПИТа браузера Интернета, т.е клиент без участия сервера.
Как делать зависит от того, как это будет использоваться. В примере с итоговыми цифрами всё зависит от того, насколько пользователь склонен запрашивать расшифровки цифр (т.е продажи по покупателям, дням, накладным). Если это часто используется, те передавать все итоговые цифры не имеет смысла. Точнее это даже вредно, т.к пользователь не по ним ходить будет, а менять страницу а ту, на которой есть подробная информация. Перегонка всего, что не будет использовано при такой работе – лишняя задержка в прорисовке страницы. Эти вещи не особо важны, когда в офисе есть широкополосный Интернет. Но если попытаться посмотреть информацию по дороге на дальнюю дачу, то скорость будет даже не 3G, а обычные 285кбт, типовые для мобильной связи. И тогда такие шероховатости начинают чувствоваться.
Языков, которые работают с интернетовскими страницами на стороне клиента два, оба скрипты, script: javascript и vbscript. На уровне скорости обработки они давно ничем не отличаются. Но первый похож на Си и удобен для тех, кто привык заканчивать строку символом «:», а второй похож на Visual Basic и удобен тем, кто привык заканчивать строку кнопкой Enter.
Здесь:
http://akostina76.ucoz.ru/blog/2016-09-22-3452
… описание работы графика, написанного на javascript.
Всё, что мне требуется чтобы нарисовать график это подключить к кнопке «Рисовать» такое действие.
function btn_pr_click()
{
Draw("Вся продукция промышленности (1922=1)","cnv_pr", "tbl_pr", document.getElementById("sel_pr").value,1,0);
}
Сама вызываемая функция Draw() не намного длиннее:
function Draw(strTitle, strCanvas, tblName, TypeGr, koeff, round) {
gr = new GR(strCanvas);
gr.Draw(strTitle, strCanvas, tblName, TypeGr, koeff, round);
}
Так выводится пятый график из описания по ссылке. Я передаю объекту
1) то, что станет заголовком, те строку "Вся продукция промышленности (1922=1)",
2) область, в которой будет нарисован график (так я указываю место и размеры) – cnv_pt
3) сами данные, содержащиеся в таблице tbl_pt
4) тип графика из выбора на экране (столбики, линии, проценты)
5) коэффициент, позволяющий выводить например миллионы в штуках если в таблице данных обычнее значения
6) округление, т.е кол-во знаков после запятой.
А это весь HTML, выводимый на экран:
<body>
<table>
<tr>
<td>
<select id="sel_pr">
<option value="lines" label="Линии"></option>
<option value="bars" label="Bars" selected="selected"></option>
<option value="bars_sum" label="Bars суммы" ></option>
<option value="bars_prc" label="Bars %" ></option>
</select>
<input id="btn_pr" value="Рисовать" type="button" onclick="btn_pr_click()" />
<table id="tbl_pr" border="1">
<tr><td>Год</td><td>Выпуск</td></tr>
<tr><td>1922</td><td>1</td></tr>
<tr><td>1940</td><td>24</td></tr>
<tr><td>1960</td><td>123</td></tr>
<tr><td>1965</td><td>186</td></tr>
<tr><td>1970</td><td>279</td></tr>
<tr><td>1975</td><td>400</td></tr>
<tr><td>1980</td><td>497</td></tr>
</table>
</td>
<td>
<canvas id="cnv_pr" height="400" width="600"></canvas>
</td>
</tr>
</table>
</body>
Самое длинное тут – список данных, по которым надо рисовать график.
Но такая лёгкость объясняется тем, что вверху написано так:
<script type="text/javascript" src="gr.js"></script>
Это подключение описания объекта GR, который и рисует график.
Строка:
gr = new GR(strCanvas);
… инициализация объекта, для чего вызван его конструктор GR()
А это уже вызов метода объекта:
gr.Draw(strTitle, strCanvas, tblName, TypeGr, koeff, round);
… Как правило его хватает для использования объекта.
Но сам объект, конечно сложнее. В нем внутри есть очень много служебной информации и мелких функций для мелких действий, которые не нужны пользователю. Но так проще было писать объект потому и появились в нем эти внутренние, служебные функции. Есть и внутренняя информация. Например какая-то функция рассчитала где должны быть линии сетки и нарисовала их. Но ведь следующая функция будет примерно там же рисовать цифры на осях графика. Не считать же опять. Логичнее и проще сохранить информацию во внутренних переменных и взять оттуда когда она потребуется.
Эта внутренняя работа скрыта за вызовом метода Draw, хотя все остальные методы можно вызывать, а значения всех переменных смотреть. Иногда эти внутренние вещи сознательно скрывают чтобы не показывать программисту, который будет использовать объект, информацию, которая ему всё рано не нужна. Но в скриптах так не делают.
Сам объект вместе с примером лежит тут:
https://yadi.sk/d/itsgxXamvZEth
Метод Draw() тоже небольшой:
GR.prototype.Draw = function(strTitle,strCanvas, tblName,TypeGr,koeff,round)
{
var ctx;
ctx = document.getElementById(strCanvas).getContext("2d");
gr.title = strTitle;
gr.GetTblInfo(tblName);
gr.TypeGr = TypeGr;
gr.koeff =koeff;
gr.round =round;
gr.CountLablelY();
gr.PrepareLabels();
gr.DrawNet(ctx);
gr.DrawTblInfo(tblName,ctx);
}
Нескольким свойствам присваиваются значения переданных параметров чтобы не писать в виде аргументов функциям – методом (функции – методы будут использовать значения свойств) и последовательно вызываются как-то внутренние методы, которые что-то делают.
Если например знаком комментария закомментировать строку вывода самих данных:
// gr.DrawTblInfo(tblName,ctx);
, то страница будет выглядеть так:
Делать так конечно не надо. Если надо получить такой эффект надо не объект менять, а вызвать вместо Draw() всё то, что там написано но без последней строки. Доступные внутренние методы повышают гибкость, в случае когда с этой штукой надо сделать что-то экзотическое.
Конструктор GR, т.е инициализация объекта обычно создаёт внутренние переменные и присваивает им значения по умолчанию. Здесь же обычно содержаться настройки, которые возможно потребуется поменять.
function GR(strCanvas)
{
var w,h;
ctx = document.getElementById(strCanvas).getContext("2d");
w = document.getElementById(strCanvas).width;
h = document.getElementById(strCanvas).height;
this.width = w; // ширина
this.height = h; // высота
this.title = "";
this.min_y = 0;
this.max_y = 100;
this.ff_italic="normal";
this.ffw="normal";
this.ff_bold="normal";
this.ff_size="10pt";
this.ff_name="Courier";
this.gr_lines = [];
this.gr_colors = ["red","blue","black","green","yellow",
"#f2a","#44f","#840", "#462", "#fc2",
"#f08","#04f","#caa","#2fa","#cc0"
];
this.x_labels = [];
this.y_labels = [];
this.x0_area = 0;
this.x1_area = 0;
this.y0_area = 0;
this.y1_area = 0;
// Пороговые значения размеров окна
this.W_large = 500; // Крупный заголовок; текст = 10pt
this.H_large = 300;
// Без заголовка ; текст = 10pt
///***************************
this.W_small = 300; // Без заголовка ; текст = xx_small
this.H_small = 150;
this.font_title = "normal normal bold 12pt Courier";
this.font_usual = "normal normal normal 10pt Courier";
this.font_small = "normal normal normal xx-small Times New Roman CYR";
this.title_color = "blue";
this.right_margin=5;
this.TypeGr = "lines"; // "lines", "bars"
this.x0_area_data = 0;
this.x1_area_data = 0;
this.min_x_step = 0;
this.min_value=0;
this.max_value=0;
this.min_sum=0;
this.max_sum=0;
this.x_levels = 1;
this.max_x_lable_width = 0
this.summs = [];
this.koeff =1;
this.round =0;
}
Например у меня предусмотрена возможность рисования только 15-ти графиков потому, что в массиве this.gr_colors есть только 15 элементов-цветов.
При этом первый график всегда будет красным (red), а второй синим. Если очень надо то это можно поменять.
Если я напишу в вызове объекта так:
function Draw(strTitle, strCanvas, tblName, TypeGr, koeff, round) {
gr = new GR(strCanvas);
gr.gr_colors[0]="blue";
gr.Draw(strTitle, strCanvas, tblName, TypeGr, koeff, round);
}
… т.е вручную переопределю цвет первого графика то я получу такое:
Вот, например, метод GetVal (получить значение):
GR.prototype.GetVal = function(nVal)
{
var nRet;
if (this.TypeGr!="bars_prc")
if (this.round==1)
nRet = Math.round(nVal / this.koeff);
else
nRet = nVal / this.koeff;
else
nRet = nVal;
return(nRet);
Всё, что он делает это делит число на коэффициент. Казалось бы можно было выполнять эту операцию и в основной функции, читающей, пишущей или суммирующей данные. Достаточно было бы написать:
Itogo = Itogo+ Val/ this.koeff;
а написано там:
Itogo = Itogo+ this.GetVal(Val);
Но это ещё одно удобство объектов как инструмента. А вдруг ещё один коэффициент появится? Не представляю зачем это может потребоваться, но а вдруг? При таком вдруг мне потребуется поменять только одну функцию потому, что весь объект обращается к ней, т.е правило считывания информации у меня вынесено в отдельный метод. При изменениях я вставлю несколько строк в одной функции. Без объекта как идеологии мне пришлось бы искать все места, где у меня берутся цифры и менять что-то там. А если бы я и без объекта завела отдельную функцию GetVal(), то мне всё равно пришлось бы добавлять новый параметр функции по все местам, где она вызывается.
p/s
Я на недельку остановлюсь. По-моему пока есть с чем экспериментировать.
|