Стартовая страница › Форумы › Разработка и интеграция › Собственные компоненты в редакторе схем
- В этой теме 76 ответов, 5 участников, последнее обновление 4 года, 10 месяцев назад сделано Mikhail.
-
АвторСообщения
-
17.05.2018 в 20:40 #9372RomirosУчастник
Будет ли возможность создания собственных компонентов схем? В виде подключаемых dll или ещё как-нибудь. Например, очень не хватает компонента линия и прогрессбар.
17.05.2018 в 21:28 #9374MikhailМодераторТакая возможность есть. Посмотрите PlgSchBasicComp
Прогресс бар, я надеюсь, будет реализован с нашей стороны, а вот линия не планируется, так что присоединяйтесь к разработке.
21.05.2018 в 19:18 #9413RomirosУчастникНасколько я понимаю, нужно дописывать собственные компоненты в исходную библиотеку, а потом просто заменять ей имеющуюся?
22.05.2018 в 15:15 #9418MikhailМодераторНужно создать свой плагин по аналогии с примером, который будет реализовывать новые компоненты в дополнение к существующим.
29.06.2018 в 09:25 #9784RomirosУчастникСозданный компонент не появляется на схеме, хотя в списке присутствует. Я так понимаю он просто не рендерится. Я никогда не косался web разработки, направьте пожалуйста.
Я взял за основу компонент button, упёрся в css. Как скомпилировать .less файл? Я понимаю что нужно использовать node.js, но не пойму как это сделать в студии. VS2017 у меня.P.S. Примера не хватает пошагового. Энтузиастов у нас на форуме полно, только знаний не хватает. Если есть профессиональные программисты, помогли бы примерами.
29.06.2018 в 18:06 #9792MikhailМодераторСозданный компонент не появляется на схеме, хотя в списке присутствует.
Посмотрите в консоли браузера, там может быть что-то полезное.
Я так понимаю он просто не рендерится.
Вполне возможно. Отрисовка компонентов происходит на JS. Посмотрите этот файл.
Как скомпилировать .less файл?
С помощью менеджера расширений VS установить WebCompiler. По правой кнопке на файле можно будет скомпилировать.
Примера не хватает пошагового.
Согласен, но пока руки не доходят. Может быть кто-то разберется и снимет видео.
29.06.2018 в 18:07 #9793MikhailМодераторВеб-программирование достаточно специфическое по сравнению с обычными приложениями. Потребуется разобраться с JavaScript, CSS (Less), HTML5.
23.08.2018 в 07:47 #10183slwIsУчастникДля создания собственного контрола нужно:
1. Написать класс который наследуется от BaseComponent и, если контрол динамический то ещё и от IDynamicComponent.
Класс пишется по аналогии с базовыми контролами, просто посмотрите как там написано, в основном вся «магия в .js» о чём далее..2. Добавить ваш класс реализующий контроллер в BasicCompFactory и в BasicCompLibSpec (предварительно нужно подключить в ресурсы изображение вашего контрола для отображения в приложениии редактора схем)
3. В файле basiccomprender.js добавить в конце:
scada.scheme.rendererMap.set(«Scada.Web.Plugins.SchBasicComp.НАЗВАНИЕ_ВАШЕГО_КЛАССА», new scada.scheme.НАЗВАНИЕ_ВАШЕГО_КЛАССАRenderer());и реализовать функции:
scada.scheme.НАЗВАНИЕ_ВАШЕГО_КЛАССАRenderer.prototype.updateData = function (component, renderContext)
{…реализация…}scada.scheme.НАЗВАНИЕ_ВАШЕГО_КЛАССАRenderer = function () {
scada.scheme.ComponentRenderer.call(this);
};scada.scheme.НАЗВАНИЕ_ВАШЕГО_КЛАССАRenderer.prototype = Object.create(scada.scheme.ComponentRenderer.prototype);
scada.scheme.НАЗВАНИЕ_ВАШЕГО_КЛАССАRenderer.constructor = scada.scheme.НАЗВАНИЕ_ВАШЕГО_КЛАССАRenderer;scada.scheme.НАЗВАНИЕ_ВАШЕГО_КЛАССАRenderer.prototype.createDom = function (component, renderContext) {…реализация…}
Если нужно могу привести пример а так же пример контрола с условиями.
Исходя из названия SchBasicComp видно что это работает при добавлении к оригинальным компонентам, но если у вас своя библиотека то структура там та же.23.08.2018 в 08:53 #10184slwIsУчастникНапример мы хотим сделать шестерёнку в формате SVG и что бы при значении канала больше нуля она крутилась и меняла цвет.
1.Добавим класс:
using Scada.Scheme.Model; using Scada.Scheme.Model.DataTypes; using Scada.Scheme.Model.PropertyGrid; using System; using System.Drawing.Design; using System.Xml; using CM = System.ComponentModel; namespace Scada.Web.Plugins.SchBasicComp { /// <summary> /// Scheme component that represents fan /// <para>Компонент схемы, представляющий шестерню</para> /// </summary> [Serializable] public class Setting : BaseComponent, IDynamicComponent { /// <summary> /// Размер кнопки по умолчанию /// </summary> public static readonly Size DefaultSize = new Size(200, 198); /// <summary> /// Конструктор /// </summary> public Setting() : base() { serBinder = PlgUtils.SerializationBinder; ColorOn = "#009846"; ColorOff = "gray"; Dur = "1s"; Action = Actions.None; InCnlNum = 0; CtrlCnlNum = 0; Size = DefaultSize; } /// <summary> /// Получить или установить продолжительность анимации /// </summary> #region Attributes [DisplayName("Dur"), Category(Categories.Behavior)] [Description("Продолжительность анимации")] [CM.DefaultValue("1s")] #endregion public string Dur { get; set; } /// <summary> /// Получить или установить цвет контрола в включенном состоянии /// </summary> #region Attributes [DisplayName("ColorOn"), Category(Categories.Appearance)] [Description("Цвет в вкюченном состоянии")] [CM.DefaultValue("#009846")] #endregion public string ColorOn { get; set; } /// <summary> /// Получить или установить цвет контрола в выключенном состоянии /// </summary> #region Attributes [DisplayName("ColorOff"), Category(Categories.Appearance)] [Description("Цвет в выкюченном состоянии")] [CM.DefaultValue("gray")] #endregion public string ColorOff { get; set; } /// <summary> /// Получить или установить действие /// </summary> #region Attributes [DisplayName("Action"), Category(Categories.Behavior)] [Description("The action executed by clicking the left mouse button on the component.")] [CM.DefaultValue(Actions.None)] #endregion public Actions Action { get; set; } /// <summary> /// Получить или установить номер входного канала /// </summary> #region Attributes [DisplayName("Input channel"), Category(Categories.Data)] [Description("The input channel number associated with the component.")] [CM.DefaultValue(0)] #endregion public int InCnlNum { get; set; } /// <summary> /// Получить или установить номер канала управления /// </summary> #region Attributes [DisplayName("Output channel"), Category(Categories.Data)] [Description("The output channel number associated with the component.")] [CM.DefaultValue(0)] #endregion public int CtrlCnlNum { get; set; } /// <summary> /// Загрузить конфигурацию компонента из XML-узла /// </summary> public override void LoadFromXml(XmlNode xmlNode) { base.LoadFromXml(xmlNode); Dur = xmlNode.GetChildAsString("Dur"); ColorOn = xmlNode.GetChildAsString("ColorOn"); ColorOff = xmlNode.GetChildAsString("ColorOff"); Action = xmlNode.GetChildAsEnum<Actions>("Action"); InCnlNum = xmlNode.GetChildAsInt("InCnlNum"); CtrlCnlNum = xmlNode.GetChildAsInt("CtrlCnlNum"); } /// <summary> /// Сохранить конфигурацию компонента в XML-узле /// </summary> public override void SaveToXml(XmlElement xmlElem) { base.SaveToXml(xmlElem); xmlElem.AppendElem("Dur", Dur); xmlElem.AppendElem("ColorOn", ColorOn); xmlElem.AppendElem("ColorOff", ColorOff); xmlElem.AppendElem("Action", Action); xmlElem.AppendElem("InCnlNum", InCnlNum); xmlElem.AppendElem("CtrlCnlNum", CtrlCnlNum); } /// <summary> /// Вернуть строковое представление объекта /// </summary> public override string ToString() { return BuildDisplayName(ToolTip); } } }
23.08.2018 в 08:58 #10185slwIsУчастник2. Добавим в BasicCompLibSpec в метод CreateCompItems():
new CompItem(Resources.setting, typeof(Setting))
Добавим в BasicCompFactory в метод CreateComponent:
else if (NameEquals("Setting", (typeof(Setting)).FullName, typeName, nameIsShort)) return new Setting();
3. Настроим отрисовку контрола в js, дабавив следущие строки:
/********** Setting Renderer **********/ scada.scheme.SettingRenderer = function () { scada.scheme.ComponentRenderer.call(this); }; scada.scheme.SettingRenderer.prototype = Object.create(scada.scheme.ComponentRenderer.prototype); scada.scheme.SettingRenderer.constructor = scada.scheme.SettingRenderer; scada.scheme.SettingRenderer.prototype.createDom = function (component, renderContext) { var props = component.props; var fComp = $("<svg id='comp" + component.id + "' data-oldval='null' clip-rule='evenodd' fill-rule='evenodd' image-rendering='optimizeQuality' text-rendering='geometricPrecision' shape-rendering='geometricPrecision' viewBox='0 0 210 210'>"+ "<g><path fill='"+props.ColorOff+"' d='M101.661,67.429c-19.261,0-34.937,15.353-34.937,34.232s15.672,34.25,34.937,34.25"+ "c19.258,0,34.926-15.371,34.926-34.25C136.587,82.779,120.919,67.429,101.661,67.429z M101.661,129.035"+ "c-15.468,0-28.044-12.286-28.044-27.375c0-15.081,12.576-27.353,28.044-27.353c15.461,0,28.037,12.272,28.037,27.353"+ "C129.698,116.753,117.121,129.035,101.661,129.035z'>"+ "<animate id='animatecomp" + component.id + "' attributeName='fill' attributeType='XML' begin='0s' dur='"+props.Dur+"' values='"+props.ColorOff+"' calcMode='discrete' fill='freeze'/>"+ "</path>"+ "<path fill='"+props.ColorOff+"' d='M176.398,77.21l-0.97-0.344l-3.783-9.019l0.412-0.927c11.442-25.947,10.658-26.723,8.754-28.606"+ "l-15.264-14.888c-0.623-0.616-1.714-1.052-2.663-1.052c-0.855,0-3.461,0-26.004,10.21l-0.902,0.404l-9.301-3.747l-0.376-0.923"+ "C115.708,2.072,114.616,2.072,111.979,2.072H90.423c-2.627,0-3.826,0-13.653,26.294l-0.369,0.956l-9.251,3.772l-0.884-0.369"+ "C51.009,26.29,42.102,23.03,39.779,23.03c-0.945,0-2.04,0.422-2.67,1.041L21.835,39.002c-1.94,1.911-2.741,2.709,9.301,28.119"+ "l0.444,0.945l-3.783,9.004l-0.927,0.358C0,87.814,0,88.824,0,91.533v21.112c0,2.713,0,3.837,26.917,13.485l0.963,0.34l3.783,8.983"+ "l-0.404,0.92c-11.445,25.961-10.719,26.662-8.768,28.599l15.239,14.913c0.641,0.616,1.743,1.052,2.684,1.052"+ "c0.852,0,3.45,0,26.004-10.203l0.902-0.426l9.309,3.765l0.365,0.934c10.608,26.24,11.699,26.24,14.337,26.24h21.563"+ "c2.706,0,3.822,0,13.66-26.315l0.372-0.956l9.266-3.754l0.884,0.365c15.246,6.453,24.147,9.706,26.458,9.706"+ "c0.938,0,2.044-0.408,2.681-1.041l15.303-14.96c1.925-1.922,2.724-2.713-9.337-28.094l-0.447-0.956l3.779-8.969l0.902-0.354"+ "c26.906-10.432,26.906-11.449,26.906-14.158V90.659C203.314,87.943,203.314,86.823,176.398,77.21z M169.741,122.25l-4.946,11.764"+ "c-0.379,0.895-0.358,1.922,0.068,2.82c3.482,7.283,8.085,17.415,9.985,22.404l0.537,1.417l-12.805,12.526l-1.342-0.447"+ "c-5.071-1.718-15.815-6.077-23.649-9.405c-0.805-0.34-1.814-0.365-2.67-0.011l-11.993,4.849c-0.898,0.365-1.603,1.092-1.94,1.986"+ "c-3.386,9.126-7.247,18.735-9.176,22.865l-0.626,1.342H93.007l-0.637-1.267c-2.38-4.731-6.807-15.203-9.913-22.923"+ "c-0.333-0.859-1.031-1.564-1.9-1.925l-12.036-4.874c-0.805-0.329-1.9-0.293-2.724,0.072c-7.727,3.536-18.123,8.049-23.069,9.853"+ "l-1.374,0.512l-12.812-12.54l0.497-1.406c1.718-4.874,6.088-15.249,9.52-22.983c0.379-0.87,0.394-1.829,0.025-2.713l-4.942-11.739"+ "c-0.376-0.895-1.102-1.585-2.022-1.911c-7.831-2.795-18.478-6.8-23.359-8.994l-1.364-0.626v-17.64l1.328-0.637"+ "c4.746-2.244,15.371-6.56,23.402-9.663c0.884-0.34,1.575-0.998,1.94-1.865l4.967-11.764c0.379-0.905,0.358-1.933-0.061-2.827"+ "c-4.141-8.661-8.335-18.095-9.981-22.414l-0.544-1.421l12.798-12.515l1.338,0.447c4.95,1.657,15.668,5.977,23.692,9.398"+ "c0.848,0.351,1.789,0.358,2.652,0.011l11.996-4.871c0.87-0.365,1.578-1.102,1.911-1.986c2.845-7.637,6.925-18.045,9.173-22.858"+ "l0.623-1.342h18.177l0.651,1.285c2.351,4.713,6.778,15.203,9.888,22.948c0.347,0.855,1.052,1.557,1.9,1.9l12.014,4.853"+ "c0.83,0.344,1.933,0.315,2.702-0.043c7.78-3.554,18.227-8.077,23.116-9.856l1.381-0.483l12.809,12.49l-0.497,1.406"+ "c-1.746,4.924-6.109,15.292-9.516,22.983c-0.387,0.877-0.387,1.854-0.018,2.756l4.942,11.76c0.372,0.891,1.102,1.585,2.022,1.918"+ "c9.427,3.343,19.022,7.015,23.345,8.947l1.385,0.623v17.608l-1.317,0.644c-4.86,2.323-15.561,6.642-23.445,9.695"+ "C170.819,120.697,170.092,121.402,169.741,122.25z'>"+ "<animate id='animatecomp2" + component.id + "' attributeName='fill' attributeType='XML' begin='0s' dur='"+props.Dur+"' values='"+props.ColorOff+"' calcMode='discrete' fill='freeze'/>"+ "</path>"+ "<animateTransform id='animateTransformcomp" + component.id + "' attributeType='XML' attributeName='transform' begin='0s' dur='"+props.Dur+"' type='rotate' from='0 102 110' to='0 102 110' repeatCount='indefinite'/>"+ "</g></svg>"); this.prepareComponent(fComp, component); this.bindAction(fComp, component, renderContext); component.dom = fComp; }; scada.scheme.SettingRenderer.prototype.updateData = function (component, renderContext) { var props = component.props; var curCnlDataExt = renderContext.curCnlDataMap.get(props.InCnlNum); var Setting = document.getElementById('comp'+component.id); if (Setting && curCnlDataExt) { if (curCnlDataExt.Val > 0 && (Setting.dataset.oldval == 0 || Setting.dataset.oldval=='null')) { var AnimEl = document.getElementById('animateTransformcomp' + component.id); AnimEl.setAttribute("from", "0 102 110"); AnimEl.setAttribute("to", "360 102 110"); AnimEl.beginElement(); var AnimElColor = document.getElementById('animatecomp' + component.id); AnimElColor.setAttribute("values", props.ColorOff+";"+props.ColorOn); AnimElColor.beginElement(); var AnimElColor2 = document.getElementById('animatecomp2' + component.id); AnimElColor2.setAttribute("values", props.ColorOff+";"+props.ColorOn); AnimElColor2.beginElement(); Setting.dataset.oldval = curCnlDataExt.Val; } if (curCnlDataExt.Val == 0 && (Setting.dataset.oldval == 1 || Setting.dataset.oldval=='null')) { var AnimEl = document.getElementById('animateTransformcomp' + component.id); AnimEl.setAttribute("from", "0 102 110"); AnimEl.setAttribute("to", "0 102 110"); AnimEl.beginElement(); var AnimElColor = document.getElementById('animatecomp' + component.id); AnimElColor.setAttribute("values", props.ColorOn+";"+props.ColorOff); AnimElColor.beginElement(); var AnimElColor2 = document.getElementById('animatecomp2' + component.id); AnimElColor2.setAttribute("values", props.ColorOn+";"+props.ColorOff); AnimElColor2.beginElement(); Setting.dataset.oldval = curCnlDataExt.Val; } } } /********** Renderer Map **********/ // Add components to the renderer map scada.scheme.rendererMap.set("Scada.Web.Plugins.SchBasicComp.Setting", new scada.scheme.SettingRenderer());
23.08.2018 в 09:02 #10186slwIsУчастникВот собственно и всё. В js можно положить в контрол всё что угодно от красочных SVG до элементов <video>, и т.д. всё ограничено только вашей фантазией и нуждами. SVG анимируется с помощью SMIL так что дополнительных библиотек не нужно.
Основная работа и оригинальность как я и писал производится в .JS.
- Этот ответ был изменен 5 лет, 8 месяцев назад от slwIs.
23.08.2018 в 17:48 #10190MikhailМодераторХорошее описание. Я мог бы его положить в отдельный раздел справки, если Вы оформите текст как в остальных страницах справки.
Также если есть собранный плагин, то можно выложить его в ропозиторий http://demo.rapidscada.net/plugins/Store/Store.aspx
24.08.2018 в 08:40 #10192slwIsУчастникhttps://drive.google.com/open?id=1UX_xEGvZuwPRIvaOgtsxdvbDhguEjTW1
Так? Или имеется ввиду собрать html? Тогда не уверен когда смогу найти время.
- Этот ответ был изменен 5 лет, 8 месяцев назад от slwIs.
24.08.2018 в 19:39 #10194RomirosУчастникСпасибо большое за пример. Буду изучать.
24.08.2018 в 19:50 #10195MikhailМодераторТак? Или имеется ввиду собрать html? Тогда не уверен когда смогу найти время.
Имел ввиду в виде html с той разметкой, как это сделано в файлах справки.
В любом случае, большое спасибо за помощь — и запись на форуме и Google Doc очень полезны. Именно наши пользователи помогают Rapid SCADA развиваться. -
АвторСообщения
- Вы должны авторизироваться для ответа в этой теме.